diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 244106a03..4916ffb61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,7 +116,9 @@ jobs: else DCO_RANGE=$(curl ${GITHUB_COMMIT_URL} | jq -r '.[0].parents[0].sha + "..HEAD"') fi - ../project/script/validate/dco + # Add back after CRI merge complete and remove last call + # ../project/script/validate/dco + echo "skipping for CRI merge since older commits may not pass this check" - name: Headers run: ../project/script/validate/fileheader ../project/ diff --git a/Makefile b/Makefile index adac53e86..a7906f8e2 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,7 @@ GO_LDFLAGS=-ldflags '-X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revi SHIM_GO_LDFLAGS=-ldflags '-X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) -X $(PKG)/version.Package=$(PACKAGE) -extldflags "-static" $(EXTRA_LDFLAGS)' # Project packages. -PACKAGES=$(shell go list ${GO_TAGS} ./... | grep -v /vendor/) +PACKAGES=$(shell go list ${GO_TAGS} ./... | grep -v /vendor/ | grep -v /integration) INTEGRATION_PACKAGE=${PKG} TEST_REQUIRES_ROOT_PACKAGES=$(filter \ ${PACKAGES}, \ diff --git a/cmd/containerd/builtins_cri.go b/cmd/containerd/builtins_cri.go index 2abc24e3a..4d5129d0d 100644 --- a/cmd/containerd/builtins_cri.go +++ b/cmd/containerd/builtins_cri.go @@ -18,4 +18,4 @@ package main -import _ "github.com/containerd/cri" +import _ "github.com/containerd/containerd/pkg/cri" diff --git a/integration/main_test.go b/integration/main_test.go index e8f4459b5..95480c382 100644 --- a/integration/main_test.go +++ b/integration/main_test.go @@ -39,12 +39,12 @@ import ( cri "k8s.io/cri-api/pkg/apis" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/integration/remote" - dialer "github.com/containerd/cri/integration/util" - criconfig "github.com/containerd/cri/pkg/config" - "github.com/containerd/cri/pkg/constants" - "github.com/containerd/cri/pkg/server" - "github.com/containerd/cri/pkg/util" + "github.com/containerd/containerd/integration/remote" + dialer "github.com/containerd/containerd/integration/util" + criconfig "github.com/containerd/containerd/pkg/config" + "github.com/containerd/containerd/pkg/constants" + "github.com/containerd/containerd/pkg/server" + "github.com/containerd/containerd/pkg/util" ) const ( diff --git a/integration/remote/remote_image.go b/integration/remote/remote_image.go index 346c370b5..121227786 100644 --- a/integration/remote/remote_image.go +++ b/integration/remote/remote_image.go @@ -44,7 +44,7 @@ import ( internalapi "k8s.io/cri-api/pkg/apis" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/integration/remote/util" + "github.com/containerd/containerd/integration/remote/util" ) // ImageService is a gRPC implementation of internalapi.ImageManagerService. diff --git a/integration/remote/remote_runtime.go b/integration/remote/remote_runtime.go index c15e7884a..dce9b9634 100644 --- a/integration/remote/remote_runtime.go +++ b/integration/remote/remote_runtime.go @@ -47,7 +47,7 @@ import ( runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" utilexec "k8s.io/utils/exec" - "github.com/containerd/cri/integration/remote/util" + "github.com/containerd/containerd/integration/remote/util" ) // RuntimeService is a gRPC implementation of internalapi.RuntimeService. diff --git a/pkg/api/runtimeoptions/v1/api.pb.go b/pkg/api/runtimeoptions/v1/api.pb.go index bf0cf3d41..63e33f475 100644 --- a/pkg/api/runtimeoptions/v1/api.pb.go +++ b/pkg/api/runtimeoptions/v1/api.pb.go @@ -1,41 +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. -*/ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: api.proto +// source: github.com/containerd/containerd/pkg/api/runtimeoptions/v1/api.proto -/* - Package cri_runtimeoptions_v1 is a generated protocol buffer package. - - It is generated from these files: - api.proto - - It has these top-level messages: - Options -*/ package cri_runtimeoptions_v1 -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" -import _ "github.com/gogo/protobuf/gogoproto" - -import strings "strings" -import reflect "reflect" - -import io "io" +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -46,19 +23,49 @@ var _ = math.Inf // 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 +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type Options struct { // TypeUrl specifies the type of the content inside the config file. TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` // ConfigPath specifies the filesystem location of the config file // used by the runtime. - ConfigPath string `protobuf:"bytes,2,opt,name=config_path,json=configPath,proto3" json:"config_path,omitempty"` + ConfigPath string `protobuf:"bytes,2,opt,name=config_path,json=configPath,proto3" json:"config_path,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Options) Reset() { *m = Options{} } -func (*Options) ProtoMessage() {} -func (*Options) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} } +func (m *Options) Reset() { *m = Options{} } +func (*Options) ProtoMessage() {} +func (*Options) Descriptor() ([]byte, []int) { + return fileDescriptor_8398b2d76ed13c1c, []int{0} +} +func (m *Options) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Options) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Options.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Options) XXX_Merge(src proto.Message) { + xxx_messageInfo_Options.Merge(m, src) +} +func (m *Options) XXX_Size() int { + return m.Size() +} +func (m *Options) XXX_DiscardUnknown() { + xxx_messageInfo_Options.DiscardUnknown(m) +} + +var xxx_messageInfo_Options proto.InternalMessageInfo func (m *Options) GetTypeUrl() string { if m != nil { @@ -77,10 +84,33 @@ func (m *Options) GetConfigPath() string { func init() { proto.RegisterType((*Options)(nil), "cri.runtimeoptions.v1.Options") } + +func init() { + proto.RegisterFile("github.com/containerd/containerd/pkg/api/runtimeoptions/v1/api.proto", fileDescriptor_8398b2d76ed13c1c) +} + +var fileDescriptor_8398b2d76ed13c1c = []byte{ + // 224 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x72, 0x49, 0xcf, 0x2c, 0xc9, + 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, + 0x4a, 0x41, 0x66, 0x16, 0x64, 0xa7, 0xeb, 0x27, 0x16, 0x64, 0xea, 0x17, 0x95, 0xe6, 0x95, 0x64, + 0xe6, 0xa6, 0xe6, 0x17, 0x94, 0x64, 0xe6, 0xe7, 0x15, 0xeb, 0x97, 0x19, 0x82, 0x44, 0xf5, 0x0a, + 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0x44, 0x93, 0x8b, 0x32, 0xf5, 0x50, 0x15, 0xe8, 0x95, 0x19, 0x4a, + 0xe9, 0x22, 0x19, 0x9e, 0x9e, 0x9f, 0x9e, 0xaf, 0x0f, 0x56, 0x9d, 0x54, 0x9a, 0x06, 0xe6, 0x81, + 0x39, 0x60, 0x16, 0xc4, 0x14, 0x25, 0x57, 0x2e, 0x76, 0x7f, 0x88, 0x66, 0x21, 0x49, 0x2e, 0x8e, + 0x92, 0xca, 0x82, 0xd4, 0xf8, 0xd2, 0xa2, 0x1c, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x76, + 0x10, 0x3f, 0xb4, 0x28, 0x47, 0x48, 0x9e, 0x8b, 0x3b, 0x39, 0x3f, 0x2f, 0x2d, 0x33, 0x3d, 0xbe, + 0x20, 0xb1, 0x24, 0x43, 0x82, 0x09, 0x2c, 0xcb, 0x05, 0x11, 0x0a, 0x48, 0x2c, 0xc9, 0x70, 0xca, + 0x3b, 0xf1, 0x50, 0x8e, 0xf1, 0xc6, 0x43, 0x39, 0x86, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x1e, 0xc9, + 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x51, 0x01, + 0xe4, 0x7b, 0xd8, 0x3a, 0xb9, 0x28, 0x33, 0x1e, 0x55, 0x34, 0xbe, 0xcc, 0x30, 0x89, 0x0d, 0xec, + 0x7a, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa5, 0x97, 0xee, 0x94, 0x4b, 0x01, 0x00, 0x00, +} + func (m *Options) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -88,35 +118,47 @@ func (m *Options) Marshal() (dAtA []byte, err error) { } func (m *Options) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Options) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.TypeUrl) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintApi(dAtA, i, uint64(len(m.TypeUrl))) - i += copy(dAtA[i:], m.TypeUrl) - } if len(m.ConfigPath) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.ConfigPath) + copy(dAtA[i:], m.ConfigPath) i = encodeVarintApi(dAtA, i, uint64(len(m.ConfigPath))) - i += copy(dAtA[i:], m.ConfigPath) + i-- + dAtA[i] = 0x12 } - return i, nil + if len(m.TypeUrl) > 0 { + i -= len(m.TypeUrl) + copy(dAtA[i:], m.TypeUrl) + i = encodeVarintApi(dAtA, i, uint64(len(m.TypeUrl))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func encodeVarintApi(dAtA []byte, offset int, v uint64) int { + offset -= sovApi(v) + base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) v >>= 7 offset++ } dAtA[offset] = uint8(v) - return offset + 1 + return base } func (m *Options) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l l = len(m.TypeUrl) @@ -131,14 +173,7 @@ func (m *Options) Size() (n int) { } func sovApi(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n + return (math_bits.Len64(x|1) + 6) / 7 } func sozApi(x uint64) (n int) { return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) @@ -177,7 +212,7 @@ func (m *Options) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -205,7 +240,7 @@ func (m *Options) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -215,6 +250,9 @@ func (m *Options) Unmarshal(dAtA []byte) error { return ErrInvalidLengthApi } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -234,7 +272,7 @@ func (m *Options) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -244,6 +282,9 @@ func (m *Options) Unmarshal(dAtA []byte) error { return ErrInvalidLengthApi } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -258,6 +299,9 @@ func (m *Options) Unmarshal(dAtA []byte) error { if skippy < 0 { return ErrInvalidLengthApi } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthApi + } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } @@ -273,6 +317,7 @@ func (m *Options) Unmarshal(dAtA []byte) error { func skipApi(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -304,10 +349,8 @@ func skipApi(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -324,71 +367,34 @@ func skipApi(dAtA []byte) (n int, err error) { break } } - iNdEx += length if length < 0 { return 0, ErrInvalidLengthApi } - return iNdEx, nil + iNdEx += length case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowApi - } - 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 := skipApi(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupApi + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthApi + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupApi = fmt.Errorf("proto: unexpected end of group") ) - -func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } - -var fileDescriptorApi = []byte{ - // 183 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x2c, 0xc8, 0xd4, - 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4d, 0x2e, 0xca, 0xd4, 0x2b, 0x2a, 0xcd, 0x2b, 0xc9, - 0xcc, 0x4d, 0xcd, 0x2f, 0x28, 0xc9, 0xcc, 0xcf, 0x2b, 0xd6, 0x2b, 0x33, 0x94, 0xd2, 0x4d, 0xcf, - 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x4f, 0xcf, 0xd7, 0x07, 0xab, - 0x4e, 0x2a, 0x4d, 0x03, 0xf3, 0xc0, 0x1c, 0x30, 0x0b, 0x62, 0x8a, 0x92, 0x2b, 0x17, 0xbb, 0x3f, - 0x44, 0xb3, 0x90, 0x24, 0x17, 0x47, 0x49, 0x65, 0x41, 0x6a, 0x7c, 0x69, 0x51, 0x8e, 0x04, 0xa3, - 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3b, 0x88, 0x1f, 0x5a, 0x94, 0x23, 0x24, 0xcf, 0xc5, 0x9d, 0x9c, - 0x9f, 0x97, 0x96, 0x99, 0x1e, 0x5f, 0x90, 0x58, 0x92, 0x21, 0xc1, 0x04, 0x96, 0xe5, 0x82, 0x08, - 0x05, 0x24, 0x96, 0x64, 0x38, 0xc9, 0x9c, 0x78, 0x28, 0xc7, 0x78, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, - 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, - 0xc2, 0x63, 0x39, 0x86, 0x24, 0x36, 0xb0, 0x5d, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, - 0x00, 0xf2, 0x18, 0xbe, 0x00, 0x00, 0x00, -} diff --git a/pkg/api/runtimeoptions/v1/api.proto b/pkg/api/runtimeoptions/v1/api.proto index 4f5b68fe5..e8bcde428 100644 --- a/pkg/api/runtimeoptions/v1/api.proto +++ b/pkg/api/runtimeoptions/v1/api.proto @@ -13,6 +13,9 @@ option (gogoproto.sizer_all) = true; option (gogoproto.unmarshaler_all) = true; option (gogoproto.goproto_unrecognized_all) = false; + +option go_package = "github.com/containerd/containerd/pkg/api/runtimeoptions/v1;cri_runtimeoptions_v1"; + message Options { // TypeUrl specifies the type of the content inside the config file. string type_url = 1; diff --git a/pkg/config/config_unix.go b/pkg/config/config_unix.go index 9df456b53..6d8523abb 100644 --- a/pkg/config/config_unix.go +++ b/pkg/config/config_unix.go @@ -21,7 +21,7 @@ package config import ( "github.com/BurntSushi/toml" "github.com/containerd/containerd" - "github.com/containerd/cri/pkg/streaming" + "github.com/containerd/containerd/pkg/streaming" ) // DefaultConfig returns default configurations of cri plugin. diff --git a/pkg/config/config_windows.go b/pkg/config/config_windows.go index d559b4160..de4593bdb 100644 --- a/pkg/config/config_windows.go +++ b/pkg/config/config_windows.go @@ -23,7 +23,7 @@ import ( "path/filepath" "github.com/containerd/containerd" - "github.com/containerd/cri/pkg/streaming" + "github.com/containerd/containerd/pkg/streaming" ) // DefaultConfig returns default configurations of cri plugin. diff --git a/pkg/containerd/opts/spec_linux.go b/pkg/containerd/opts/spec_linux.go index e358d8d6e..a52c68a3c 100644 --- a/pkg/containerd/opts/spec_linux.go +++ b/pkg/containerd/opts/spec_linux.go @@ -40,8 +40,8 @@ import ( "golang.org/x/sys/unix" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - osinterface "github.com/containerd/cri/pkg/os" - "github.com/containerd/cri/pkg/util" + osinterface "github.com/containerd/containerd/pkg/os" + "github.com/containerd/containerd/pkg/util" ) // WithAdditionalGIDs adds any additional groups listed for a particular user in the diff --git a/pkg/containerd/opts/spec_windows.go b/pkg/containerd/opts/spec_windows.go index 50ee19d48..f6d4a1648 100644 --- a/pkg/containerd/opts/spec_windows.go +++ b/pkg/containerd/opts/spec_windows.go @@ -30,7 +30,7 @@ import ( "github.com/pkg/errors" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - osinterface "github.com/containerd/cri/pkg/os" + osinterface "github.com/containerd/containerd/pkg/os" ) // WithWindowsNetworkNamespace sets windows network namespace for container. diff --git a/pkg/containerd/util/util.go b/pkg/containerd/util/util.go index ec062df0d..27f2167af 100644 --- a/pkg/containerd/util/util.go +++ b/pkg/containerd/util/util.go @@ -22,7 +22,7 @@ import ( "github.com/containerd/containerd/namespaces" "golang.org/x/net/context" - "github.com/containerd/cri/pkg/constants" + "github.com/containerd/containerd/pkg/constants" ) // deferCleanupTimeout is the default timeout for containerd cleanup operations diff --git a/pkg/cri/cri.go b/pkg/cri/cri.go index 7d9cc5fc7..6150723fd 100644 --- a/pkg/cri/cri.go +++ b/pkg/cri/cri.go @@ -39,10 +39,10 @@ import ( "github.com/sirupsen/logrus" "k8s.io/klog/v2" - criconfig "github.com/containerd/cri/pkg/config" - "github.com/containerd/cri/pkg/constants" - criplatforms "github.com/containerd/cri/pkg/containerd/platforms" - "github.com/containerd/cri/pkg/server" + criconfig "github.com/containerd/containerd/pkg/config" + "github.com/containerd/containerd/pkg/constants" + criplatforms "github.com/containerd/containerd/pkg/containerd/platforms" + "github.com/containerd/containerd/pkg/server" ) // TODO(random-liu): Use github.com/pkg/errors for our errors. diff --git a/pkg/os/testing/fake_os.go b/pkg/os/testing/fake_os.go index 957b77424..c4f1bf6cc 100644 --- a/pkg/os/testing/fake_os.go +++ b/pkg/os/testing/fake_os.go @@ -22,7 +22,7 @@ import ( containerdmount "github.com/containerd/containerd/mount" - osInterface "github.com/containerd/cri/pkg/os" + osInterface "github.com/containerd/containerd/pkg/os" ) // CalledDetail is the struct contains called function name and arguments. diff --git a/pkg/os/testing/fake_os_unix.go b/pkg/os/testing/fake_os_unix.go index 67fa4baca..9a1639489 100644 --- a/pkg/os/testing/fake_os_unix.go +++ b/pkg/os/testing/fake_os_unix.go @@ -18,6 +18,6 @@ package testing -import osInterface "github.com/containerd/cri/pkg/os" +import osInterface "github.com/containerd/containerd/pkg/os" var _ osInterface.UNIX = &FakeOS{} diff --git a/pkg/server/container_attach.go b/pkg/server/container_attach.go index c8101ff7c..9f06e25ad 100644 --- a/pkg/server/container_attach.go +++ b/pkg/server/container_attach.go @@ -26,7 +26,7 @@ import ( "k8s.io/client-go/tools/remotecommand" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - cio "github.com/containerd/cri/pkg/server/io" + cio "github.com/containerd/containerd/pkg/server/io" ) // Attach prepares a streaming endpoint to attach to a running container, and returns the address. diff --git a/pkg/server/container_create.go b/pkg/server/container_create.go index 01eac7bc8..ae7762a23 100644 --- a/pkg/server/container_create.go +++ b/pkg/server/container_create.go @@ -33,16 +33,16 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - customopts "github.com/containerd/cri/pkg/containerd/opts" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - cio "github.com/containerd/cri/pkg/server/io" - containerstore "github.com/containerd/cri/pkg/store/container" - "github.com/containerd/cri/pkg/util" + customopts "github.com/containerd/containerd/pkg/containerd/opts" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + cio "github.com/containerd/containerd/pkg/server/io" + containerstore "github.com/containerd/containerd/pkg/store/container" + "github.com/containerd/containerd/pkg/util" ) func init() { typeurl.Register(&containerstore.Metadata{}, - "github.com/containerd/cri/pkg/store/container", "Metadata") + "github.com/containerd/containerd/pkg/store/container", "Metadata") } // CreateContainer creates a new container in the given PodSandbox. diff --git a/pkg/server/container_create_linux.go b/pkg/server/container_create_linux.go index 0b930394e..db32b7559 100644 --- a/pkg/server/container_create_linux.go +++ b/pkg/server/container_create_linux.go @@ -34,9 +34,9 @@ import ( "github.com/pkg/errors" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - "github.com/containerd/cri/pkg/config" - customopts "github.com/containerd/cri/pkg/containerd/opts" + "github.com/containerd/containerd/pkg/annotations" + "github.com/containerd/containerd/pkg/config" + customopts "github.com/containerd/containerd/pkg/containerd/opts" ) const ( diff --git a/pkg/server/container_create_linux_test.go b/pkg/server/container_create_linux_test.go index 7187ec383..843f8ed08 100644 --- a/pkg/server/container_create_linux_test.go +++ b/pkg/server/container_create_linux_test.go @@ -40,12 +40,12 @@ import ( "github.com/stretchr/testify/require" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - "github.com/containerd/cri/pkg/config" - "github.com/containerd/cri/pkg/containerd/opts" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - ostesting "github.com/containerd/cri/pkg/os/testing" - "github.com/containerd/cri/pkg/util" + "github.com/containerd/containerd/pkg/annotations" + "github.com/containerd/containerd/pkg/config" + "github.com/containerd/containerd/pkg/containerd/opts" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + ostesting "github.com/containerd/containerd/pkg/os/testing" + "github.com/containerd/containerd/pkg/util" ) func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandboxConfig, diff --git a/pkg/server/container_create_other.go b/pkg/server/container_create_other.go index 82bbb87e0..12e5ae95c 100644 --- a/pkg/server/container_create_other.go +++ b/pkg/server/container_create_other.go @@ -24,7 +24,7 @@ import ( runtimespec "github.com/opencontainers/runtime-spec/specs-go" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/config" + "github.com/containerd/containerd/pkg/config" ) // containerMounts sets up necessary container system file mounts diff --git a/pkg/server/container_create_test.go b/pkg/server/container_create_test.go index b1c6cc8b3..3fadd48f2 100644 --- a/pkg/server/container_create_test.go +++ b/pkg/server/container_create_test.go @@ -28,9 +28,9 @@ import ( "github.com/stretchr/testify/require" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/config" - "github.com/containerd/cri/pkg/constants" - "github.com/containerd/cri/pkg/containerd/opts" + "github.com/containerd/containerd/pkg/config" + "github.com/containerd/containerd/pkg/constants" + "github.com/containerd/containerd/pkg/containerd/opts" ) func checkMount(t *testing.T, mounts []runtimespec.Mount, src, dest, typ string, diff --git a/pkg/server/container_create_windows.go b/pkg/server/container_create_windows.go index 86a08d89e..f41447650 100644 --- a/pkg/server/container_create_windows.go +++ b/pkg/server/container_create_windows.go @@ -24,9 +24,9 @@ import ( runtimespec "github.com/opencontainers/runtime-spec/specs-go" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - "github.com/containerd/cri/pkg/config" - customopts "github.com/containerd/cri/pkg/containerd/opts" + "github.com/containerd/containerd/pkg/annotations" + "github.com/containerd/containerd/pkg/config" + customopts "github.com/containerd/containerd/pkg/containerd/opts" ) // No container mounts for windows. diff --git a/pkg/server/container_create_windows_test.go b/pkg/server/container_create_windows_test.go index 42f14d692..8de431f5d 100644 --- a/pkg/server/container_create_windows_test.go +++ b/pkg/server/container_create_windows_test.go @@ -26,8 +26,8 @@ import ( "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - "github.com/containerd/cri/pkg/config" + "github.com/containerd/containerd/pkg/annotations" + "github.com/containerd/containerd/pkg/config" ) func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandboxConfig, diff --git a/pkg/server/container_execsync.go b/pkg/server/container_execsync.go index 1c019f651..7397d7055 100644 --- a/pkg/server/container_execsync.go +++ b/pkg/server/container_execsync.go @@ -32,10 +32,10 @@ import ( "k8s.io/client-go/tools/remotecommand" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - cioutil "github.com/containerd/cri/pkg/ioutil" - cio "github.com/containerd/cri/pkg/server/io" - "github.com/containerd/cri/pkg/util" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + cioutil "github.com/containerd/containerd/pkg/ioutil" + cio "github.com/containerd/containerd/pkg/server/io" + "github.com/containerd/containerd/pkg/util" ) // ExecSync executes a command in the container, and returns the stdout output. diff --git a/pkg/server/container_list.go b/pkg/server/container_list.go index c9e88d13d..c27e231df 100644 --- a/pkg/server/container_list.go +++ b/pkg/server/container_list.go @@ -21,7 +21,7 @@ import ( runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) // ListContainers lists all containers matching the filter. diff --git a/pkg/server/container_list_test.go b/pkg/server/container_list_test.go index ccee3ce5a..a80d516a7 100644 --- a/pkg/server/container_list_test.go +++ b/pkg/server/container_list_test.go @@ -25,8 +25,8 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containerstore "github.com/containerd/cri/pkg/store/container" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + containerstore "github.com/containerd/containerd/pkg/store/container" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) func TestToCRIContainer(t *testing.T) { diff --git a/pkg/server/container_remove.go b/pkg/server/container_remove.go index 6426635dd..15f982d2f 100644 --- a/pkg/server/container_remove.go +++ b/pkg/server/container_remove.go @@ -25,8 +25,8 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" + "github.com/containerd/containerd/pkg/store" + containerstore "github.com/containerd/containerd/pkg/store/container" ) // RemoveContainer removes the container. diff --git a/pkg/server/container_remove_test.go b/pkg/server/container_remove_test.go index 7093f4808..d1afd372a 100644 --- a/pkg/server/container_remove_test.go +++ b/pkg/server/container_remove_test.go @@ -22,7 +22,7 @@ import ( "github.com/stretchr/testify/assert" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) // TestSetContainerRemoving tests setContainerRemoving sets removing diff --git a/pkg/server/container_start.go b/pkg/server/container_start.go index 4be89c9a6..79c7f761e 100644 --- a/pkg/server/container_start.go +++ b/pkg/server/container_start.go @@ -31,11 +31,11 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - cioutil "github.com/containerd/cri/pkg/ioutil" - cio "github.com/containerd/cri/pkg/server/io" - containerstore "github.com/containerd/cri/pkg/store/container" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + cioutil "github.com/containerd/containerd/pkg/ioutil" + cio "github.com/containerd/containerd/pkg/server/io" + containerstore "github.com/containerd/containerd/pkg/store/container" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) // StartContainer starts the container. diff --git a/pkg/server/container_start_test.go b/pkg/server/container_start_test.go index 644bb45cd..5ca308687 100644 --- a/pkg/server/container_start_test.go +++ b/pkg/server/container_start_test.go @@ -22,7 +22,7 @@ import ( "github.com/stretchr/testify/assert" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) // TestSetContainerStarting tests setContainerStarting sets removing diff --git a/pkg/server/container_stats_list.go b/pkg/server/container_stats_list.go index 0a9be8741..3b6ea29ac 100644 --- a/pkg/server/container_stats_list.go +++ b/pkg/server/container_stats_list.go @@ -23,7 +23,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) // ListContainerStats returns stats of all running containers. diff --git a/pkg/server/container_stats_list_linux.go b/pkg/server/container_stats_list_linux.go index d160b0928..82b040d3f 100644 --- a/pkg/server/container_stats_list_linux.go +++ b/pkg/server/container_stats_list_linux.go @@ -26,7 +26,7 @@ import ( "github.com/pkg/errors" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) func (c *criService) containerMetrics( diff --git a/pkg/server/container_stats_list_other.go b/pkg/server/container_stats_list_other.go index b4bc28ff5..02a99978a 100644 --- a/pkg/server/container_stats_list_other.go +++ b/pkg/server/container_stats_list_other.go @@ -24,7 +24,7 @@ import ( "github.com/pkg/errors" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) func (c *criService) containerMetrics( diff --git a/pkg/server/container_stats_list_windows.go b/pkg/server/container_stats_list_windows.go index 4bd3b64c1..733a06d07 100644 --- a/pkg/server/container_stats_list_windows.go +++ b/pkg/server/container_stats_list_windows.go @@ -25,7 +25,7 @@ import ( "github.com/pkg/errors" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) func (c *criService) containerMetrics( diff --git a/pkg/server/container_status.go b/pkg/server/container_status.go index aeeb76db3..952660efa 100644 --- a/pkg/server/container_status.go +++ b/pkg/server/container_status.go @@ -24,8 +24,8 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" + "github.com/containerd/containerd/pkg/store" + containerstore "github.com/containerd/containerd/pkg/store/container" ) // ContainerStatus inspects the container and returns the status. diff --git a/pkg/server/container_status_test.go b/pkg/server/container_status_test.go index 7ee9ed087..da036aac7 100644 --- a/pkg/server/container_status_test.go +++ b/pkg/server/container_status_test.go @@ -24,8 +24,8 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containerstore "github.com/containerd/cri/pkg/store/container" - imagestore "github.com/containerd/cri/pkg/store/image" + containerstore "github.com/containerd/containerd/pkg/store/container" + imagestore "github.com/containerd/containerd/pkg/store/image" ) func getContainerStatusTestData() (*containerstore.Metadata, *containerstore.Status, diff --git a/pkg/server/container_stop.go b/pkg/server/container_stop.go index 92075d6b6..469376e45 100644 --- a/pkg/server/container_stop.go +++ b/pkg/server/container_stop.go @@ -28,9 +28,9 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + "github.com/containerd/containerd/pkg/store" + containerstore "github.com/containerd/containerd/pkg/store/container" ) // StopContainer stops a running container with a grace period (i.e., timeout). diff --git a/pkg/server/container_stop_test.go b/pkg/server/container_stop_test.go index 8394f62e0..8d2fa140a 100644 --- a/pkg/server/container_stop_test.go +++ b/pkg/server/container_stop_test.go @@ -23,7 +23,7 @@ import ( "github.com/stretchr/testify/assert" "golang.org/x/net/context" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) func TestWaitContainerStop(t *testing.T) { diff --git a/pkg/server/container_update_resources_linux.go b/pkg/server/container_update_resources_linux.go index ce3f8a812..6857575bd 100644 --- a/pkg/server/container_update_resources_linux.go +++ b/pkg/server/container_update_resources_linux.go @@ -29,10 +29,10 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/containerd/opts" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - containerstore "github.com/containerd/cri/pkg/store/container" - "github.com/containerd/cri/pkg/util" + "github.com/containerd/containerd/pkg/containerd/opts" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + containerstore "github.com/containerd/containerd/pkg/store/container" + "github.com/containerd/containerd/pkg/util" ) // UpdateContainerResources updates ContainerConfig of the container. diff --git a/pkg/server/container_update_resources_other.go b/pkg/server/container_update_resources_other.go index 57975fdc3..e4370324b 100644 --- a/pkg/server/container_update_resources_other.go +++ b/pkg/server/container_update_resources_other.go @@ -23,7 +23,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containerstore "github.com/containerd/cri/pkg/store/container" + containerstore "github.com/containerd/containerd/pkg/store/container" ) // UpdateContainerResources updates ContainerConfig of the container. diff --git a/pkg/server/events.go b/pkg/server/events.go index 8f35bf0bd..b9aabe597 100644 --- a/pkg/server/events.go +++ b/pkg/server/events.go @@ -32,11 +32,11 @@ import ( "golang.org/x/net/context" "k8s.io/apimachinery/pkg/util/clock" - "github.com/containerd/cri/pkg/constants" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + "github.com/containerd/containerd/pkg/constants" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + "github.com/containerd/containerd/pkg/store" + containerstore "github.com/containerd/containerd/pkg/store/container" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) const ( diff --git a/pkg/server/helpers.go b/pkg/server/helpers.go index 34da9a254..0e09d0321 100644 --- a/pkg/server/helpers.go +++ b/pkg/server/helpers.go @@ -37,12 +37,12 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - runtimeoptions "github.com/containerd/cri/pkg/api/runtimeoptions/v1" - criconfig "github.com/containerd/cri/pkg/config" - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" - imagestore "github.com/containerd/cri/pkg/store/image" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + runtimeoptions "github.com/containerd/containerd/pkg/api/runtimeoptions/v1" + criconfig "github.com/containerd/containerd/pkg/config" + "github.com/containerd/containerd/pkg/store" + containerstore "github.com/containerd/containerd/pkg/store/container" + imagestore "github.com/containerd/containerd/pkg/store/image" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) const ( diff --git a/pkg/server/helpers_linux.go b/pkg/server/helpers_linux.go index 6b8b048dc..6fc70ede8 100644 --- a/pkg/server/helpers_linux.go +++ b/pkg/server/helpers_linux.go @@ -30,8 +30,8 @@ import ( "github.com/containerd/containerd/log" "github.com/containerd/containerd/mount" - "github.com/containerd/cri/pkg/seccomp" - "github.com/containerd/cri/pkg/seutil" + "github.com/containerd/containerd/pkg/seccomp" + "github.com/containerd/containerd/pkg/seutil" runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" diff --git a/pkg/server/helpers_test.go b/pkg/server/helpers_test.go index 4bb38e736..fa65002b2 100644 --- a/pkg/server/helpers_test.go +++ b/pkg/server/helpers_test.go @@ -32,9 +32,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - criconfig "github.com/containerd/cri/pkg/config" - "github.com/containerd/cri/pkg/store" - imagestore "github.com/containerd/cri/pkg/store/image" + criconfig "github.com/containerd/containerd/pkg/config" + "github.com/containerd/containerd/pkg/store" + imagestore "github.com/containerd/containerd/pkg/store/image" ) // TestGetUserFromImage tests the logic of getting image uid or user name of image user. diff --git a/pkg/server/image_list_test.go b/pkg/server/image_list_test.go index 315470324..c630f19d2 100644 --- a/pkg/server/image_list_test.go +++ b/pkg/server/image_list_test.go @@ -25,7 +25,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - imagestore "github.com/containerd/cri/pkg/store/image" + imagestore "github.com/containerd/containerd/pkg/store/image" ) func TestListImages(t *testing.T) { diff --git a/pkg/server/image_pull.go b/pkg/server/image_pull.go index 8e2493613..d6627bd04 100644 --- a/pkg/server/image_pull.go +++ b/pkg/server/image_pull.go @@ -42,7 +42,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - criconfig "github.com/containerd/cri/pkg/config" + criconfig "github.com/containerd/containerd/pkg/config" ) // For image management: diff --git a/pkg/server/image_pull_test.go b/pkg/server/image_pull_test.go index 551e68bae..c41039c1a 100644 --- a/pkg/server/image_pull_test.go +++ b/pkg/server/image_pull_test.go @@ -28,7 +28,7 @@ import ( "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - criconfig "github.com/containerd/cri/pkg/config" + criconfig "github.com/containerd/containerd/pkg/config" ) func TestParseAuth(t *testing.T) { diff --git a/pkg/server/image_remove.go b/pkg/server/image_remove.go index bcd02d758..ec54b9d55 100644 --- a/pkg/server/image_remove.go +++ b/pkg/server/image_remove.go @@ -23,7 +23,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/store" + "github.com/containerd/containerd/pkg/store" ) // RemoveImage removes the image. diff --git a/pkg/server/image_status.go b/pkg/server/image_status.go index 5ada7b007..ad6502d38 100644 --- a/pkg/server/image_status.go +++ b/pkg/server/image_status.go @@ -25,8 +25,8 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/store" - imagestore "github.com/containerd/cri/pkg/store/image" + "github.com/containerd/containerd/pkg/store" + imagestore "github.com/containerd/containerd/pkg/store/image" ) // ImageStatus returns the status of the image, returns nil if the image isn't present. diff --git a/pkg/server/image_status_test.go b/pkg/server/image_status_test.go index 5b3bc7af0..f91b19588 100644 --- a/pkg/server/image_status_test.go +++ b/pkg/server/image_status_test.go @@ -25,7 +25,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - imagestore "github.com/containerd/cri/pkg/store/image" + imagestore "github.com/containerd/containerd/pkg/store/image" ) func TestImageStatus(t *testing.T) { diff --git a/pkg/server/imagefs_info_test.go b/pkg/server/imagefs_info_test.go index b36c1aafb..bf4bdb267 100644 --- a/pkg/server/imagefs_info_test.go +++ b/pkg/server/imagefs_info_test.go @@ -25,7 +25,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - snapshotstore "github.com/containerd/cri/pkg/store/snapshot" + snapshotstore "github.com/containerd/containerd/pkg/store/snapshot" ) func TestImageFsInfo(t *testing.T) { diff --git a/pkg/server/instrumented_service.go b/pkg/server/instrumented_service.go index 2c2528ab6..9d3288c48 100644 --- a/pkg/server/instrumented_service.go +++ b/pkg/server/instrumented_service.go @@ -24,7 +24,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" ) // instrumentedService wraps service with containerd namespace and logs. diff --git a/pkg/server/io/container_io.go b/pkg/server/io/container_io.go index c66549ca5..edb929e93 100644 --- a/pkg/server/io/container_io.go +++ b/pkg/server/io/container_io.go @@ -25,8 +25,8 @@ import ( "github.com/containerd/containerd/cio" "github.com/sirupsen/logrus" - cioutil "github.com/containerd/cri/pkg/ioutil" - "github.com/containerd/cri/pkg/util" + cioutil "github.com/containerd/containerd/pkg/ioutil" + "github.com/containerd/containerd/pkg/util" ) // streamKey generates a key for the stream. diff --git a/pkg/server/io/exec_io.go b/pkg/server/io/exec_io.go index 4a695030d..667977fda 100644 --- a/pkg/server/io/exec_io.go +++ b/pkg/server/io/exec_io.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/containerd/cio" "github.com/sirupsen/logrus" - cioutil "github.com/containerd/cri/pkg/ioutil" + cioutil "github.com/containerd/containerd/pkg/ioutil" ) // ExecIO holds the exec io. diff --git a/pkg/server/io/logger.go b/pkg/server/io/logger.go index f13b6f8bf..22d50db9d 100644 --- a/pkg/server/io/logger.go +++ b/pkg/server/io/logger.go @@ -27,7 +27,7 @@ import ( "github.com/sirupsen/logrus" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - cioutil "github.com/containerd/cri/pkg/ioutil" + cioutil "github.com/containerd/containerd/pkg/ioutil" ) const ( diff --git a/pkg/server/io/logger_test.go b/pkg/server/io/logger_test.go index 6c91a049a..f63e274a8 100644 --- a/pkg/server/io/logger_test.go +++ b/pkg/server/io/logger_test.go @@ -27,7 +27,7 @@ import ( "github.com/stretchr/testify/require" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - cioutil "github.com/containerd/cri/pkg/ioutil" + cioutil "github.com/containerd/containerd/pkg/ioutil" ) func TestRedirectLogs(t *testing.T) { diff --git a/pkg/server/restart.go b/pkg/server/restart.go index 2480bd5ea..fb3b3e174 100644 --- a/pkg/server/restart.go +++ b/pkg/server/restart.go @@ -34,11 +34,11 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/netns" - cio "github.com/containerd/cri/pkg/server/io" - containerstore "github.com/containerd/cri/pkg/store/container" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + "github.com/containerd/containerd/pkg/netns" + cio "github.com/containerd/containerd/pkg/server/io" + containerstore "github.com/containerd/containerd/pkg/store/container" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) // NOTE: The recovery logic has following assumption: when the cri plugin is down: diff --git a/pkg/server/sandbox_list.go b/pkg/server/sandbox_list.go index d2528b267..50e552d7c 100644 --- a/pkg/server/sandbox_list.go +++ b/pkg/server/sandbox_list.go @@ -20,7 +20,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) // ListPodSandbox returns a list of Sandbox. diff --git a/pkg/server/sandbox_list_test.go b/pkg/server/sandbox_list_test.go index af67bbfeb..f22285889 100644 --- a/pkg/server/sandbox_list_test.go +++ b/pkg/server/sandbox_list_test.go @@ -23,7 +23,7 @@ import ( "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) func TestToCRISandbox(t *testing.T) { diff --git a/pkg/server/sandbox_portforward.go b/pkg/server/sandbox_portforward.go index 6d382ba2b..15d9ed635 100644 --- a/pkg/server/sandbox_portforward.go +++ b/pkg/server/sandbox_portforward.go @@ -21,7 +21,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) // PortForward prepares a streaming endpoint to forward ports from a PodSandbox, and returns the address. diff --git a/pkg/server/sandbox_portforward_windows.go b/pkg/server/sandbox_portforward_windows.go index 3c328a314..127ef2b50 100644 --- a/pkg/server/sandbox_portforward_windows.go +++ b/pkg/server/sandbox_portforward_windows.go @@ -27,8 +27,8 @@ import ( "golang.org/x/net/context" "k8s.io/utils/exec" - "github.com/containerd/cri/pkg/ioutil" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + "github.com/containerd/containerd/pkg/ioutil" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) func (c *criService) portForward(ctx context.Context, id string, port int32, stream io.ReadWriter) error { diff --git a/pkg/server/sandbox_remove.go b/pkg/server/sandbox_remove.go index 2c2deb2e0..929528664 100644 --- a/pkg/server/sandbox_remove.go +++ b/pkg/server/sandbox_remove.go @@ -25,8 +25,8 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/store" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + "github.com/containerd/containerd/pkg/store" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) // RemovePodSandbox removes the sandbox. If there are running containers in the diff --git a/pkg/server/sandbox_run.go b/pkg/server/sandbox_run.go index e0b207d7a..cc6e8d6fa 100644 --- a/pkg/server/sandbox_run.go +++ b/pkg/server/sandbox_run.go @@ -36,20 +36,20 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - criconfig "github.com/containerd/cri/pkg/config" - customopts "github.com/containerd/cri/pkg/containerd/opts" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/netns" - "github.com/containerd/cri/pkg/server/bandwidth" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" - "github.com/containerd/cri/pkg/util" + "github.com/containerd/containerd/pkg/annotations" + criconfig "github.com/containerd/containerd/pkg/config" + customopts "github.com/containerd/containerd/pkg/containerd/opts" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + "github.com/containerd/containerd/pkg/netns" + "github.com/containerd/containerd/pkg/server/bandwidth" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" + "github.com/containerd/containerd/pkg/util" selinux "github.com/opencontainers/selinux/go-selinux" ) func init() { typeurl.Register(&sandboxstore.Metadata{}, - "github.com/containerd/cri/pkg/store/sandbox", "Metadata") + "github.com/containerd/containerd/pkg/store/sandbox", "Metadata") } // RunPodSandbox creates and starts a pod-level sandbox. Runtimes should ensure diff --git a/pkg/server/sandbox_run_linux.go b/pkg/server/sandbox_run_linux.go index f886d2ae2..ee506470f 100644 --- a/pkg/server/sandbox_run_linux.go +++ b/pkg/server/sandbox_run_linux.go @@ -31,9 +31,9 @@ import ( "golang.org/x/sys/unix" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - customopts "github.com/containerd/cri/pkg/containerd/opts" - osinterface "github.com/containerd/cri/pkg/os" + "github.com/containerd/containerd/pkg/annotations" + customopts "github.com/containerd/containerd/pkg/containerd/opts" + osinterface "github.com/containerd/containerd/pkg/os" ) func (c *criService) sandboxContainerSpec(id string, config *runtime.PodSandboxConfig, diff --git a/pkg/server/sandbox_run_linux_test.go b/pkg/server/sandbox_run_linux_test.go index 166cd6f9e..78f21d0c2 100644 --- a/pkg/server/sandbox_run_linux_test.go +++ b/pkg/server/sandbox_run_linux_test.go @@ -28,9 +28,9 @@ import ( "github.com/stretchr/testify/require" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - "github.com/containerd/cri/pkg/containerd/opts" - ostesting "github.com/containerd/cri/pkg/os/testing" + "github.com/containerd/containerd/pkg/annotations" + "github.com/containerd/containerd/pkg/containerd/opts" + ostesting "github.com/containerd/containerd/pkg/os/testing" ) func getRunPodSandboxTestData() (*runtime.PodSandboxConfig, *imagespec.ImageConfig, func(*testing.T, string, *runtimespec.Spec)) { diff --git a/pkg/server/sandbox_run_test.go b/pkg/server/sandbox_run_test.go index 70f01ce03..cb06b8cba 100644 --- a/pkg/server/sandbox_run_test.go +++ b/pkg/server/sandbox_run_test.go @@ -27,9 +27,9 @@ import ( "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - criconfig "github.com/containerd/cri/pkg/config" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + "github.com/containerd/containerd/pkg/annotations" + criconfig "github.com/containerd/containerd/pkg/config" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) func TestSandboxContainerSpec(t *testing.T) { diff --git a/pkg/server/sandbox_run_windows.go b/pkg/server/sandbox_run_windows.go index 85105c299..27404de25 100644 --- a/pkg/server/sandbox_run_windows.go +++ b/pkg/server/sandbox_run_windows.go @@ -26,8 +26,8 @@ import ( "github.com/pkg/errors" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - customopts "github.com/containerd/cri/pkg/containerd/opts" + "github.com/containerd/containerd/pkg/annotations" + customopts "github.com/containerd/containerd/pkg/containerd/opts" ) func (c *criService) sandboxContainerSpec(id string, config *runtime.PodSandboxConfig, diff --git a/pkg/server/sandbox_run_windows_test.go b/pkg/server/sandbox_run_windows_test.go index 96d2c1c74..7061fa431 100644 --- a/pkg/server/sandbox_run_windows_test.go +++ b/pkg/server/sandbox_run_windows_test.go @@ -26,8 +26,8 @@ import ( "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" - "github.com/containerd/cri/pkg/containerd/opts" + "github.com/containerd/containerd/pkg/annotations" + "github.com/containerd/containerd/pkg/containerd/opts" ) func getRunPodSandboxTestData() (*runtime.PodSandboxConfig, *imagespec.ImageConfig, func(*testing.T, string, *runtimespec.Spec)) { diff --git a/pkg/server/sandbox_status.go b/pkg/server/sandbox_status.go index 5644ab1be..66b4919bf 100644 --- a/pkg/server/sandbox_status.go +++ b/pkg/server/sandbox_status.go @@ -28,7 +28,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) // PodSandboxStatus returns the status of the PodSandbox. diff --git a/pkg/server/sandbox_status_test.go b/pkg/server/sandbox_status_test.go index 894f945f5..d09d253e6 100644 --- a/pkg/server/sandbox_status_test.go +++ b/pkg/server/sandbox_status_test.go @@ -23,7 +23,7 @@ import ( "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) func TestPodSandboxStatus(t *testing.T) { diff --git a/pkg/server/sandbox_stop.go b/pkg/server/sandbox_stop.go index 9b6e0a6ec..a931505e5 100644 --- a/pkg/server/sandbox_stop.go +++ b/pkg/server/sandbox_stop.go @@ -27,8 +27,8 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) // StopPodSandbox stops the sandbox. If there are any running containers in the diff --git a/pkg/server/sandbox_stop_test.go b/pkg/server/sandbox_stop_test.go index 59083e5b3..53d8ca477 100644 --- a/pkg/server/sandbox_stop_test.go +++ b/pkg/server/sandbox_stop_test.go @@ -23,7 +23,7 @@ import ( "github.com/stretchr/testify/assert" "golang.org/x/net/context" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" ) func TestWaitSandboxStop(t *testing.T) { diff --git a/pkg/server/service.go b/pkg/server/service.go index 94e02591a..bd0b480bb 100644 --- a/pkg/server/service.go +++ b/pkg/server/service.go @@ -27,25 +27,25 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/pkg/streaming" "github.com/containerd/containerd/plugin" - "github.com/containerd/cri/pkg/streaming" cni "github.com/containerd/go-cni" "github.com/pkg/errors" "github.com/sirupsen/logrus" "google.golang.org/grpc" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/store/label" + "github.com/containerd/containerd/pkg/store/label" - "github.com/containerd/cri/pkg/atomic" - criconfig "github.com/containerd/cri/pkg/config" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - osinterface "github.com/containerd/cri/pkg/os" - "github.com/containerd/cri/pkg/registrar" - containerstore "github.com/containerd/cri/pkg/store/container" - imagestore "github.com/containerd/cri/pkg/store/image" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" - snapshotstore "github.com/containerd/cri/pkg/store/snapshot" + "github.com/containerd/containerd/pkg/atomic" + criconfig "github.com/containerd/containerd/pkg/config" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + osinterface "github.com/containerd/containerd/pkg/os" + "github.com/containerd/containerd/pkg/registrar" + containerstore "github.com/containerd/containerd/pkg/store/container" + imagestore "github.com/containerd/containerd/pkg/store/image" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" + snapshotstore "github.com/containerd/containerd/pkg/store/snapshot" ) // grpcServices are all the grpc services provided by cri containerd. diff --git a/pkg/server/service_test.go b/pkg/server/service_test.go index a39f0b9ce..fe09b9471 100644 --- a/pkg/server/service_test.go +++ b/pkg/server/service_test.go @@ -26,15 +26,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - criconfig "github.com/containerd/cri/pkg/config" - ostesting "github.com/containerd/cri/pkg/os/testing" - "github.com/containerd/cri/pkg/registrar" - servertesting "github.com/containerd/cri/pkg/server/testing" - containerstore "github.com/containerd/cri/pkg/store/container" - imagestore "github.com/containerd/cri/pkg/store/image" - "github.com/containerd/cri/pkg/store/label" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" - snapshotstore "github.com/containerd/cri/pkg/store/snapshot" + criconfig "github.com/containerd/containerd/pkg/config" + ostesting "github.com/containerd/containerd/pkg/os/testing" + "github.com/containerd/containerd/pkg/registrar" + servertesting "github.com/containerd/containerd/pkg/server/testing" + containerstore "github.com/containerd/containerd/pkg/store/container" + imagestore "github.com/containerd/containerd/pkg/store/image" + "github.com/containerd/containerd/pkg/store/label" + sandboxstore "github.com/containerd/containerd/pkg/store/sandbox" + snapshotstore "github.com/containerd/containerd/pkg/store/snapshot" ) const ( diff --git a/pkg/server/snapshots.go b/pkg/server/snapshots.go index 0c1670750..33d8d7ec4 100644 --- a/pkg/server/snapshots.go +++ b/pkg/server/snapshots.go @@ -25,8 +25,8 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - snapshotstore "github.com/containerd/cri/pkg/store/snapshot" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + snapshotstore "github.com/containerd/containerd/pkg/store/snapshot" ) // snapshotsSyncer syncs snapshot stats periodically. imagefs info and container stats diff --git a/pkg/server/streaming.go b/pkg/server/streaming.go index d0089cc89..d08759cff 100644 --- a/pkg/server/streaming.go +++ b/pkg/server/streaming.go @@ -32,8 +32,8 @@ import ( k8scert "k8s.io/client-go/util/cert" "k8s.io/utils/exec" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/streaming" + ctrdutil "github.com/containerd/containerd/pkg/containerd/util" + "github.com/containerd/containerd/pkg/streaming" ) type streamListenerMode int diff --git a/pkg/server/streaming_test.go b/pkg/server/streaming_test.go index 0e6f8d2a5..3d085796a 100644 --- a/pkg/server/streaming_test.go +++ b/pkg/server/streaming_test.go @@ -19,7 +19,7 @@ package server import ( "testing" - "github.com/containerd/cri/pkg/config" + "github.com/containerd/containerd/pkg/config" "github.com/stretchr/testify/assert" ) diff --git a/pkg/server/update_runtime_config_test.go b/pkg/server/update_runtime_config_test.go index 2e62c8fd9..1bb45d5bd 100644 --- a/pkg/server/update_runtime_config_test.go +++ b/pkg/server/update_runtime_config_test.go @@ -28,8 +28,8 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - criconfig "github.com/containerd/cri/pkg/config" - servertesting "github.com/containerd/cri/pkg/server/testing" + criconfig "github.com/containerd/containerd/pkg/config" + servertesting "github.com/containerd/containerd/pkg/server/testing" ) func TestUpdateRuntimeConfig(t *testing.T) { diff --git a/pkg/server/version.go b/pkg/server/version.go index c1dea50c1..8c0e88611 100644 --- a/pkg/server/version.go +++ b/pkg/server/version.go @@ -21,7 +21,7 @@ import ( "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/constants" + "github.com/containerd/containerd/pkg/constants" ) const ( diff --git a/pkg/store/container/container.go b/pkg/store/container/container.go index 53c0745a5..1b75113a5 100644 --- a/pkg/store/container/container.go +++ b/pkg/store/container/container.go @@ -20,12 +20,12 @@ import ( "sync" "github.com/containerd/containerd" - "github.com/containerd/cri/pkg/store/label" + "github.com/containerd/containerd/pkg/store/label" "github.com/docker/docker/pkg/truncindex" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - cio "github.com/containerd/cri/pkg/server/io" - "github.com/containerd/cri/pkg/store" + cio "github.com/containerd/containerd/pkg/server/io" + "github.com/containerd/containerd/pkg/store" ) // Container contains all resources associated with the container. All methods to diff --git a/pkg/store/container/container_test.go b/pkg/store/container/container_test.go index a88bc02c2..9ab264b37 100644 --- a/pkg/store/container/container_test.go +++ b/pkg/store/container/container_test.go @@ -21,13 +21,13 @@ import ( "testing" "time" - "github.com/containerd/cri/pkg/store/label" + "github.com/containerd/containerd/pkg/store/label" "github.com/opencontainers/selinux/go-selinux" assertlib "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - cio "github.com/containerd/cri/pkg/server/io" - "github.com/containerd/cri/pkg/store" + cio "github.com/containerd/containerd/pkg/server/io" + "github.com/containerd/containerd/pkg/store" ) func TestContainerStore(t *testing.T) { diff --git a/pkg/store/image/image.go b/pkg/store/image/image.go index 208d490db..cb70701c3 100644 --- a/pkg/store/image/image.go +++ b/pkg/store/image/image.go @@ -30,8 +30,8 @@ import ( imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" - storeutil "github.com/containerd/cri/pkg/store" - "github.com/containerd/cri/pkg/util" + storeutil "github.com/containerd/containerd/pkg/store" + "github.com/containerd/containerd/pkg/util" ) // Image contains all resources associated with the image. All fields diff --git a/pkg/store/image/image_test.go b/pkg/store/image/image_test.go index 5635469f3..5f5fcc2d2 100644 --- a/pkg/store/image/image_test.go +++ b/pkg/store/image/image_test.go @@ -24,7 +24,7 @@ import ( "github.com/opencontainers/go-digest/digestset" assertlib "github.com/stretchr/testify/assert" - storeutil "github.com/containerd/cri/pkg/store" + storeutil "github.com/containerd/containerd/pkg/store" ) func TestInternalStore(t *testing.T) { diff --git a/pkg/store/sandbox/sandbox.go b/pkg/store/sandbox/sandbox.go index 223e88369..3dc2029dd 100644 --- a/pkg/store/sandbox/sandbox.go +++ b/pkg/store/sandbox/sandbox.go @@ -20,11 +20,11 @@ import ( "sync" "github.com/containerd/containerd" - "github.com/containerd/cri/pkg/store/label" + "github.com/containerd/containerd/pkg/store/label" "github.com/docker/docker/pkg/truncindex" - "github.com/containerd/cri/pkg/netns" - "github.com/containerd/cri/pkg/store" + "github.com/containerd/containerd/pkg/netns" + "github.com/containerd/containerd/pkg/store" ) // Sandbox contains all resources associated with the sandbox. All methods to diff --git a/pkg/store/sandbox/sandbox_test.go b/pkg/store/sandbox/sandbox_test.go index 4c922eeb8..eff3bb612 100644 --- a/pkg/store/sandbox/sandbox_test.go +++ b/pkg/store/sandbox/sandbox_test.go @@ -19,11 +19,11 @@ package sandbox import ( "testing" - "github.com/containerd/cri/pkg/store/label" + "github.com/containerd/containerd/pkg/store/label" assertlib "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/store" + "github.com/containerd/containerd/pkg/store" ) func TestSandboxStore(t *testing.T) { diff --git a/pkg/store/snapshot/snapshot.go b/pkg/store/snapshot/snapshot.go index ce05f0e04..206f5f7b2 100644 --- a/pkg/store/snapshot/snapshot.go +++ b/pkg/store/snapshot/snapshot.go @@ -21,7 +21,7 @@ import ( snapshot "github.com/containerd/containerd/snapshots" - "github.com/containerd/cri/pkg/store" + "github.com/containerd/containerd/pkg/store" ) // Snapshot contains the information about the snapshot. diff --git a/pkg/store/snapshot/snapshot_test.go b/pkg/store/snapshot/snapshot_test.go index f15107e11..eff909d94 100644 --- a/pkg/store/snapshot/snapshot_test.go +++ b/pkg/store/snapshot/snapshot_test.go @@ -23,7 +23,7 @@ import ( snapshot "github.com/containerd/containerd/snapshots" assertlib "github.com/stretchr/testify/assert" - "github.com/containerd/cri/pkg/store" + "github.com/containerd/containerd/pkg/store" ) func TestSnapshotStore(t *testing.T) { diff --git a/pkg/streaming/server.go b/pkg/streaming/server.go index 589c9a8ca..ee904dbda 100644 --- a/pkg/streaming/server.go +++ b/pkg/streaming/server.go @@ -52,8 +52,8 @@ import ( "k8s.io/client-go/tools/remotecommand" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/streaming/portforward" - remotecommandserver "github.com/containerd/cri/pkg/streaming/remotecommand" + "github.com/containerd/containerd/pkg/streaming/portforward" + remotecommandserver "github.com/containerd/containerd/pkg/streaming/remotecommand" ) // Server is the library interface to serve the stream requests. diff --git a/vendor.conf b/vendor.conf index 52eba58fe..2e566f083 100644 --- a/vendor.conf +++ b/vendor.conf @@ -57,7 +57,6 @@ gotest.tools/v3 v3.0.2 github.com/cilium/ebpf 1c8d4c9ef7759622653a1d319284a44652333b28 # cri dependencies -github.com/containerd/cri 210a86ca5bf6c8ca5f2553272d72c774b21fdec2 # master github.com/davecgh/go-spew v1.1.1 github.com/docker/docker 4634ce647cf2ce2c6031129ccd109e557244986f github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 @@ -68,6 +67,8 @@ github.com/json-iterator/go v1.1.10 github.com/modern-go/concurrent 1.0.3 github.com/modern-go/reflect2 v1.0.1 github.com/opencontainers/selinux v1.6.0 +github.com/pmezard/go-difflib v1.0.0 +github.com/stretchr/testify v1.4.0 github.com/tchap/go-patricia v2.2.6 github.com/willf/bitset v1.1.11 golang.org/x/crypto 75b288015ac94e66e3d6715fb68a9b41bf046ec2 @@ -79,6 +80,7 @@ k8s.io/api v0.19.0-rc.4 k8s.io/apimachinery v0.19.0-rc.4 k8s.io/apiserver v0.19.0-rc.4 k8s.io/client-go v0.19.0-rc.4 +k8s.io/component-base v0.19.2 k8s.io/cri-api v0.19.0-rc.4 k8s.io/klog/v2 v2.2.0 k8s.io/utils 2df71ebbae66f39338aed4cd0bb82d2212ee33cc diff --git a/vendor/github.com/containerd/cri/README.md b/vendor/github.com/containerd/cri/README.md deleted file mode 100644 index 9f80a26a1..000000000 --- a/vendor/github.com/containerd/cri/README.md +++ /dev/null @@ -1,189 +0,0 @@ -# cri -

- - -

- -*Note: The standalone `cri-containerd` binary is end-of-life. `cri-containerd` is -transitioning from a standalone binary that talks to containerd to a plugin within -containerd. This github branch is for the `cri` plugin. See -[standalone-cri-containerd branch](https://github.com/containerd/cri/tree/standalone-cri-containerd) -for information about the standalone version of `cri-containerd`.* - -*Note: You need to [drain your node](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/) before upgrading from standalone `cri-containerd` to containerd with `cri` plugin.* - -[![Build Status](https://api.travis-ci.org/containerd/cri.svg?style=flat-square)](https://travis-ci.org/containerd/cri) -[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/cri)](https://goreportcard.com/report/github.com/containerd/cri) - -`cri` is a [containerd](https://containerd.io/) plugin implementation of Kubernetes [container runtime interface (CRI)](https://github.com/kubernetes/cri-api/blob/master/pkg/apis/runtime/v1alpha2/api.proto). - -With it, you could run Kubernetes using containerd as the container runtime. -![cri](./docs/cri.png) -## Current Status -`cri` is a native plugin of containerd 1.1 and above. It is built into containerd and enabled by default. - -`cri` is in GA: -* It is feature complete. -* It (the GA version) works with Kubernetes 1.10 and above. -* It has passed all [CRI validation tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/cri-validation.md). -* It has passed all [node e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/e2e-node-tests.md). -* It has passed all [e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-testing/e2e-tests.md). - -See [test dashboard](https://k8s-testgrid.appspot.com/sig-node-containerd) -## Support Metrics -| CRI-Containerd Version | Containerd Version | Kubernetes Version | CRI Version | -|:----------------------:|:------------------:|:------------------:|:-----------:| -| v1.0.0-alpha.x | | 1.7, 1.8 | v1alpha1 | -| v1.0.0-beta.x | | 1.9 | v1alpha1 | -| End-Of-Life | v1.1 (End-Of-Life) | 1.10+ | v1alpha2 | -| | v1.2 (Extended) | 1.10+ | v1alpha2 | -| | v1.3 | 1.12+ | v1alpha2 | -| | v1.4 | 1.19+ (rc) | v1alpha2 | - -**Note:** The support table above specifies the Kubernetes Version that was supported at time of release of the containerd - cri integration. - -The following is the current support table for containerd CRI integration taking into account that Kubernetes only supports n-3 minor release versions. - -| Containerd Version | Kubernetes Version | CRI Version | -|:------------------:|:------------------:|:-----------:| -| v1.2 | 1.15+ | v1alpha2 | -| v1.3 | 1.15+ | v1alpha2 | -| v1.4 | 1.19+ (rc) | v1alpha2 | - -## Production Quality Cluster on GCE -For a production quality cluster on GCE brought up with `kube-up.sh` refer [here](docs/kube-up.md). -## Installing with Ansible and Kubeadm -For a multi node cluster installer and bring up steps using ansible and kubeadm refer [here](contrib/ansible/README.md). -## Custom Installation -For non ansible users, you can download the `cri-containerd` release tarball and deploy -kubernetes cluster using kubeadm as described [here](docs/installation.md). -## Getting Started for Developers -### Binary Dependencies and Specifications -The current release of the `cri` plugin has the following dependencies: -* [containerd](https://github.com/containerd/containerd) -* [runc](https://github.com/opencontainers/runc) -* [CNI](https://github.com/containernetworking/cni) - -See [versions](./vendor.conf) of these dependencies `cri` is tested with. - -As containerd and runc move to their respective general availability releases, -we will do our best to rebase/retest `cri` with these releases on a -weekly/monthly basis. Similarly, given that `cri` uses the Open -Container Initiative (OCI) [image](https://github.com/opencontainers/image-spec) -and [runtime](https://github.com/opencontainers/runtime-spec) specifications, we -will also do our best to update `cri` to the latest releases of these -specifications as appropriate. -### Install Dependencies -1. Install development libraries: -* **libseccomp development library.** Required by `cri` and runc seccomp support. `libseccomp-dev` (Ubuntu, Debian) / `libseccomp-devel` -(Fedora, CentOS, RHEL). On releases of Ubuntu <=Trusty and Debian <=jessie a -backport version of `libseccomp-dev` is required. See [travis.yml](.travis.yml) for an example on trusty. -* **btrfs development library.** Required by containerd btrfs support. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL) -2. Install **`pkg-config`** (required for linking with `libseccomp`). -3. Install and setup a Go 1.13.15 development environment. -4. Make a local clone of this repository. -5. Install binary dependencies by running the following command from your cloned `cri/` project directory: -```bash -# Note: install.deps installs the above mentioned runc, containerd, and CNI -# binary dependencies. install.deps is only provided for general use and ease of -# testing. To customize `runc` and `containerd` build tags and/or to configure -# `cni`, please follow instructions in their documents. -make install.deps -``` -### Build and Install `cri` -To build and install a version of containerd with the `cri` plugin, enter the -following commands from your `cri` project directory: -```bash -make -sudo make install -``` -*NOTE: The version of containerd built and installed from the `Makefile` is only for -testing purposes. The version tag carries the suffix "-TEST".* -#### Build Tags -`cri` supports optional build tags for compiling support of various features. -To add build tags to the make option the `BUILD_TAGS` variable must be set. - -```bash -make BUILD_TAGS='seccomp apparmor selinux' -``` - -| Build Tag | Feature | Dependency | -|-----------|------------------------------------|---------------------------------| -| seccomp | syscall filtering | libseccomp development library | -| selinux | selinux process and mount labeling | | -| apparmor | apparmor profile support | | -### Validate Your `cri` Setup -A Kubernetes incubator project called [cri-tools](https://github.com/kubernetes-sigs/cri-tools) -includes programs for exercising CRI implementations such as the `cri` plugin. -More importantly, cri-tools includes the program `critest` which is used for running -[CRI Validation Testing](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/cri-validation.md). - -Run the CRI Validation test to validate your installation of `containerd` with `cri` built in: -```bash -make test-cri -``` -### Running a Kubernetes local cluster -If you already have a working development environment for supported Kubernetes -version, you can try `cri` in a local cluster: - -1. Start the version of `containerd` with `cri` plugin that you built and installed -above as root in a first terminal: -```bash -sudo containerd -``` -2. From the Kubernetes project directory startup a local cluster using `containerd`: -```bash -CONTAINER_RUNTIME=remote CONTAINER_RUNTIME_ENDPOINT='unix:///run/containerd/containerd.sock' ./hack/local-up-cluster.sh -``` -### Test -See [here](./docs/testing.md) for information about test. -## Using crictl -See [here](./docs/crictl.md) for information about using `crictl` to debug -pods, containers, and images. -## Configurations -See [here](./docs/config.md) for information about how to configure cri plugins -and [here](https://github.com/containerd/containerd/blob/master/docs/man/containerd-config.8.md) -for information about how to configure containerd -## Documentation -See [here](./docs) for additional documentation. -## Communication -For async communication and long running discussions please use issues and pull -requests on this github repo. This will be the best place to discuss design and -implementation. - -For sync communication catch us in the `#containerd` and `#containerd-dev` slack -channels on Cloud Native Computing Foundation's (CNCF) slack - -`cloud-native.slack.com`. Everyone is welcome to join and chat. -[Get Invite to CNCF slack.](https://slack.cncf.io) - -## Other Communications -As this project is tightly coupled to CRI and CRI-Tools and they are Kubernetes -projects, some of our project communications take place in the Kubernetes' SIG: -`sig-node.` - -For more information about `sig-node`, `CRI`, and the `CRI-Tools` projects: -* [sig-node community site](https://github.com/kubernetes/community/tree/master/sig-node) -* Slack: `#sig-node` channel in Kubernetes (kubernetes.slack.com) -* Mailing List: https://groups.google.com/forum/#!forum/kubernetes-sig-node - -### Reporting Security Issues - -__If you are reporting a security issue, please reach out discreetly at security@containerd.io__. - -## Licenses -The containerd codebase is released under the [Apache 2.0 license](https://github.com/containerd/containerd/blob/master/LICENSE.code). -The README.md file, and files in the "docs" folder are licensed under the -Creative Commons Attribution 4.0 International License under the terms and -conditions set forth in the file "[LICENSE.docs](https://github.com/containerd/containerd/blob/master/LICENSE.docs)". You may obtain a duplicate -copy of the same license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/. - -## Project details -cri is a containerd sub-project. This project was originally established in -April of 2017 in the Kubernetes Incubator program. After reaching the Beta -stage, In January of 2018, the project was merged into [containerd](https://github.com/containerd/containerd). -As a containerd sub-project, you will find the: -* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md), -* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS), -* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md) - -information in our [`containerd/project`](https://github.com/containerd/project) repository. diff --git a/vendor/github.com/containerd/cri/cri.go b/vendor/github.com/containerd/cri/cri.go deleted file mode 100644 index 7d9cc5fc7..000000000 --- a/vendor/github.com/containerd/cri/cri.go +++ /dev/null @@ -1,192 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package cri - -import ( - "flag" - "path/filepath" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/api/services/containers/v1" - "github.com/containerd/containerd/api/services/diff/v1" - "github.com/containerd/containerd/api/services/images/v1" - introspectionapi "github.com/containerd/containerd/api/services/introspection/v1" - "github.com/containerd/containerd/api/services/namespaces/v1" - "github.com/containerd/containerd/api/services/tasks/v1" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/platforms" - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/services" - "github.com/containerd/containerd/snapshots" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "k8s.io/klog/v2" - - criconfig "github.com/containerd/cri/pkg/config" - "github.com/containerd/cri/pkg/constants" - criplatforms "github.com/containerd/cri/pkg/containerd/platforms" - "github.com/containerd/cri/pkg/server" -) - -// TODO(random-liu): Use github.com/pkg/errors for our errors. -// Register CRI service plugin -func init() { - config := criconfig.DefaultConfig() - plugin.Register(&plugin.Registration{ - Type: plugin.GRPCPlugin, - ID: "cri", - Config: &config, - Requires: []plugin.Type{ - plugin.ServicePlugin, - }, - InitFn: initCRIService, - }) -} - -func initCRIService(ic *plugin.InitContext) (interface{}, error) { - ic.Meta.Platforms = []imagespec.Platform{platforms.DefaultSpec()} - ic.Meta.Exports = map[string]string{"CRIVersion": constants.CRIVersion} - ctx := ic.Context - pluginConfig := ic.Config.(*criconfig.PluginConfig) - if err := criconfig.ValidatePluginConfig(ctx, pluginConfig); err != nil { - return nil, errors.Wrap(err, "invalid plugin config") - } - - c := criconfig.Config{ - PluginConfig: *pluginConfig, - ContainerdRootDir: filepath.Dir(ic.Root), - ContainerdEndpoint: ic.Address, - RootDir: ic.Root, - StateDir: ic.State, - } - log.G(ctx).Infof("Start cri plugin with config %+v", c) - - if err := setGLogLevel(); err != nil { - return nil, errors.Wrap(err, "failed to set glog level") - } - - servicesOpts, err := getServicesOpts(ic) - if err != nil { - return nil, errors.Wrap(err, "failed to get services") - } - - log.G(ctx).Info("Connect containerd service") - client, err := containerd.New( - "", - containerd.WithDefaultNamespace(constants.K8sContainerdNamespace), - containerd.WithDefaultPlatform(criplatforms.Default()), - containerd.WithServices(servicesOpts...), - ) - if err != nil { - return nil, errors.Wrap(err, "failed to create containerd client") - } - - s, err := server.NewCRIService(c, client) - if err != nil { - return nil, errors.Wrap(err, "failed to create CRI service") - } - - go func() { - if err := s.Run(); err != nil { - log.G(ctx).WithError(err).Fatal("Failed to run CRI service") - } - // TODO(random-liu): Whether and how we can stop containerd. - }() - return s, nil -} - -// getServicesOpts get service options from plugin context. -func getServicesOpts(ic *plugin.InitContext) ([]containerd.ServicesOpt, error) { - plugins, err := ic.GetByType(plugin.ServicePlugin) - if err != nil { - return nil, errors.Wrap(err, "failed to get service plugin") - } - - opts := []containerd.ServicesOpt{ - containerd.WithEventService(ic.Events), - } - for s, fn := range map[string]func(interface{}) containerd.ServicesOpt{ - services.ContentService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithContentStore(s.(content.Store)) - }, - services.ImagesService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithImageService(s.(images.ImagesClient)) - }, - services.SnapshotsService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithSnapshotters(s.(map[string]snapshots.Snapshotter)) - }, - services.ContainersService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithContainerService(s.(containers.ContainersClient)) - }, - services.TasksService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithTaskService(s.(tasks.TasksClient)) - }, - services.DiffService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithDiffService(s.(diff.DiffClient)) - }, - services.NamespacesService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithNamespaceService(s.(namespaces.NamespacesClient)) - }, - services.LeasesService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithLeasesService(s.(leases.Manager)) - }, - services.IntrospectionService: func(s interface{}) containerd.ServicesOpt { - return containerd.WithIntrospectionService(s.(introspectionapi.IntrospectionClient)) - }, - } { - p := plugins[s] - if p == nil { - return nil, errors.Errorf("service %q not found", s) - } - i, err := p.Instance() - if err != nil { - return nil, errors.Wrapf(err, "failed to get instance of service %q", s) - } - if i == nil { - return nil, errors.Errorf("instance of service %q not found", s) - } - opts = append(opts, fn(i)) - } - return opts, nil -} - -// Set glog level. -func setGLogLevel() error { - l := logrus.GetLevel() - fs := flag.NewFlagSet("klog", flag.PanicOnError) - klog.InitFlags(fs) - if err := fs.Set("logtostderr", "true"); err != nil { - return err - } - switch l { - case logrus.TraceLevel: - return fs.Set("v", "5") - case logrus.DebugLevel: - return fs.Set("v", "4") - case logrus.InfoLevel: - return fs.Set("v", "2") - // glog doesn't support following filters. Defaults to v=0. - case logrus.WarnLevel: - case logrus.ErrorLevel: - case logrus.FatalLevel: - case logrus.PanicLevel: - } - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/annotations/annotations.go b/vendor/github.com/containerd/cri/pkg/annotations/annotations.go deleted file mode 100644 index 122c4c489..000000000 --- a/vendor/github.com/containerd/cri/pkg/annotations/annotations.go +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package annotations - -// ContainerType values -// Following OCI annotations are used by katacontainers now. -// We'll switch to standard secure pod API after it is defined in CRI. -const ( - // ContainerTypeSandbox represents a pod sandbox container - ContainerTypeSandbox = "sandbox" - - // ContainerTypeContainer represents a container running within a pod - ContainerTypeContainer = "container" - - // ContainerType is the container type (sandbox or container) annotation - ContainerType = "io.kubernetes.cri.container-type" - - // SandboxID is the sandbox ID annotation - SandboxID = "io.kubernetes.cri.sandbox-id" - - // SandboxLogDir is the pod log directory annotation. - // If the sandbox needs to generate any log, it will put it into this directory. - // Kubelet will be responsible for: - // 1) Monitoring the disk usage of the log, and including it as part of the pod - // ephemeral storage usage. - // 2) Cleaning up the logs when the pod is deleted. - // NOTE: Kubelet is not responsible for rotating the logs. - SandboxLogDir = "io.kubernetes.cri.sandbox-log-directory" - - // UntrustedWorkload is the sandbox annotation for untrusted workload. Untrusted - // workload can only run on dedicated runtime for untrusted workload. - UntrustedWorkload = "io.kubernetes.cri.untrusted-workload" - - // containerName is the name of the container in the pod - ContainerName = "io.kubernetes.cri.container-name" -) diff --git a/vendor/github.com/containerd/cri/pkg/api/runtimeoptions/v1/api.pb.go b/vendor/github.com/containerd/cri/pkg/api/runtimeoptions/v1/api.pb.go deleted file mode 100644 index bf0cf3d41..000000000 --- a/vendor/github.com/containerd/cri/pkg/api/runtimeoptions/v1/api.pb.go +++ /dev/null @@ -1,394 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: api.proto - -/* - Package cri_runtimeoptions_v1 is a generated protocol buffer package. - - It is generated from these files: - api.proto - - It has these top-level messages: - Options -*/ -package cri_runtimeoptions_v1 - -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" -import _ "github.com/gogo/protobuf/gogoproto" - -import strings "strings" -import reflect "reflect" - -import io "io" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -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 - -type Options struct { - // TypeUrl specifies the type of the content inside the config file. - TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` - // ConfigPath specifies the filesystem location of the config file - // used by the runtime. - ConfigPath string `protobuf:"bytes,2,opt,name=config_path,json=configPath,proto3" json:"config_path,omitempty"` -} - -func (m *Options) Reset() { *m = Options{} } -func (*Options) ProtoMessage() {} -func (*Options) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} } - -func (m *Options) GetTypeUrl() string { - if m != nil { - return m.TypeUrl - } - return "" -} - -func (m *Options) GetConfigPath() string { - if m != nil { - return m.ConfigPath - } - return "" -} - -func init() { - proto.RegisterType((*Options)(nil), "cri.runtimeoptions.v1.Options") -} -func (m *Options) 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 *Options) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.TypeUrl) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintApi(dAtA, i, uint64(len(m.TypeUrl))) - i += copy(dAtA[i:], m.TypeUrl) - } - if len(m.ConfigPath) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintApi(dAtA, i, uint64(len(m.ConfigPath))) - i += copy(dAtA[i:], m.ConfigPath) - } - return i, nil -} - -func encodeVarintApi(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 *Options) Size() (n int) { - var l int - _ = l - l = len(m.TypeUrl) - if l > 0 { - n += 1 + l + sovApi(uint64(l)) - } - l = len(m.ConfigPath) - if l > 0 { - n += 1 + l + sovApi(uint64(l)) - } - return n -} - -func sovApi(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} -func sozApi(x uint64) (n int) { - return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (this *Options) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&Options{`, - `TypeUrl:` + fmt.Sprintf("%v", this.TypeUrl) + `,`, - `ConfigPath:` + fmt.Sprintf("%v", this.ConfigPath) + `,`, - `}`, - }, "") - return s -} -func valueToStringApi(v interface{}) string { - rv := reflect.ValueOf(v) - if rv.IsNil() { - return "nil" - } - pv := reflect.Indirect(rv).Interface() - return fmt.Sprintf("*%v", pv) -} -func (m *Options) 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 ErrIntOverflowApi - } - 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: Options: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Options: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TypeUrl", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowApi - } - 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 ErrInvalidLengthApi - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.TypeUrl = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConfigPath", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowApi - } - 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 ErrInvalidLengthApi - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ConfigPath = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipApi(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthApi - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipApi(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, ErrIntOverflowApi - } - 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, ErrIntOverflowApi - } - 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, ErrIntOverflowApi - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - iNdEx += length - if length < 0 { - return 0, ErrInvalidLengthApi - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowApi - } - 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 := skipApi(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - 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 ( - ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") -) - -func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } - -var fileDescriptorApi = []byte{ - // 183 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x2c, 0xc8, 0xd4, - 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4d, 0x2e, 0xca, 0xd4, 0x2b, 0x2a, 0xcd, 0x2b, 0xc9, - 0xcc, 0x4d, 0xcd, 0x2f, 0x28, 0xc9, 0xcc, 0xcf, 0x2b, 0xd6, 0x2b, 0x33, 0x94, 0xd2, 0x4d, 0xcf, - 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x4f, 0xcf, 0xd7, 0x07, 0xab, - 0x4e, 0x2a, 0x4d, 0x03, 0xf3, 0xc0, 0x1c, 0x30, 0x0b, 0x62, 0x8a, 0x92, 0x2b, 0x17, 0xbb, 0x3f, - 0x44, 0xb3, 0x90, 0x24, 0x17, 0x47, 0x49, 0x65, 0x41, 0x6a, 0x7c, 0x69, 0x51, 0x8e, 0x04, 0xa3, - 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3b, 0x88, 0x1f, 0x5a, 0x94, 0x23, 0x24, 0xcf, 0xc5, 0x9d, 0x9c, - 0x9f, 0x97, 0x96, 0x99, 0x1e, 0x5f, 0x90, 0x58, 0x92, 0x21, 0xc1, 0x04, 0x96, 0xe5, 0x82, 0x08, - 0x05, 0x24, 0x96, 0x64, 0x38, 0xc9, 0x9c, 0x78, 0x28, 0xc7, 0x78, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, - 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, - 0xc2, 0x63, 0x39, 0x86, 0x24, 0x36, 0xb0, 0x5d, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, - 0x00, 0xf2, 0x18, 0xbe, 0x00, 0x00, 0x00, -} diff --git a/vendor/github.com/containerd/cri/pkg/api/runtimeoptions/v1/api.proto b/vendor/github.com/containerd/cri/pkg/api/runtimeoptions/v1/api.proto deleted file mode 100644 index f907d609c..000000000 --- a/vendor/github.com/containerd/cri/pkg/api/runtimeoptions/v1/api.proto +++ /dev/null @@ -1,22 +0,0 @@ -// To regenerate api.pb.go run `make proto` -syntax = "proto3"; - -package cri.runtimeoptions.v1; - -import "github.com/gogo/protobuf/gogoproto/gogo.proto"; - -option (gogoproto.goproto_stringer_all) = false; -option (gogoproto.stringer_all) = true; -option (gogoproto.goproto_getters_all) = true; -option (gogoproto.marshaler_all) = true; -option (gogoproto.sizer_all) = true; -option (gogoproto.unmarshaler_all) = true; -option (gogoproto.goproto_unrecognized_all) = false; - -message Options { - // TypeUrl specifies the type of the content inside the config file. - string type_url = 1; - // ConfigPath specifies the filesystem location of the config file - // used by the runtime. - string config_path = 2; -} diff --git a/vendor/github.com/containerd/cri/pkg/atomic/atomic_boolean.go b/vendor/github.com/containerd/cri/pkg/atomic/atomic_boolean.go deleted file mode 100644 index 507e063dc..000000000 --- a/vendor/github.com/containerd/cri/pkg/atomic/atomic_boolean.go +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package atomic - -import "sync/atomic" - -// Bool is an atomic Boolean, -// Its methods are all atomic, thus safe to be called by -// multiple goroutines simultaneously. -type Bool interface { - Set() - Unset() - IsSet() bool -} - -// NewBool creates an Bool with given default value -func NewBool(ok bool) Bool { - ab := new(atomicBool) - if ok { - ab.Set() - } - return ab -} - -type atomicBool int32 - -// Set sets the Boolean to true -func (ab *atomicBool) Set() { - atomic.StoreInt32((*int32)(ab), 1) -} - -// Unset sets the Boolean to false -func (ab *atomicBool) Unset() { - atomic.StoreInt32((*int32)(ab), 0) -} - -// IsSet returns whether the Boolean is true -func (ab *atomicBool) IsSet() bool { - return atomic.LoadInt32((*int32)(ab)) == 1 -} diff --git a/vendor/github.com/containerd/cri/pkg/config/config.go b/vendor/github.com/containerd/cri/pkg/config/config.go deleted file mode 100644 index a0c86fa76..000000000 --- a/vendor/github.com/containerd/cri/pkg/config/config.go +++ /dev/null @@ -1,369 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package config - -import ( - "context" - "time" - - "github.com/BurntSushi/toml" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/plugin" - "github.com/pkg/errors" -) - -// Runtime struct to contain the type(ID), engine, and root variables for a default runtime -// and a runtime for untrusted worload. -type Runtime struct { - // Type is the runtime type to use in containerd e.g. io.containerd.runtime.v1.linux - Type string `toml:"runtime_type" json:"runtimeType"` - // Engine is the name of the runtime engine used by containerd. - // This only works for runtime type "io.containerd.runtime.v1.linux". - // DEPRECATED: use Options instead. Remove when shim v1 is deprecated. - Engine string `toml:"runtime_engine" json:"runtimeEngine"` - // PodAnnotations is a list of pod annotations passed to both pod sandbox as well as - // container OCI annotations. - PodAnnotations []string `toml:"pod_annotations" json:"PodAnnotations"` - // ContainerAnnotations is a list of container annotations passed through to the OCI config of the containers. - // Container annotations in CRI are usually generated by other Kubernetes node components (i.e., not users). - // Currently, only device plugins populate the annotations. - ContainerAnnotations []string `toml:"container_annotations" json:"ContainerAnnotations"` - // Root is the directory used by containerd for runtime state. - // DEPRECATED: use Options instead. Remove when shim v1 is deprecated. - // This only works for runtime type "io.containerd.runtime.v1.linux". - Root string `toml:"runtime_root" json:"runtimeRoot"` - // Options are config options for the runtime. If options is loaded - // from toml config, it will be toml.Primitive. - Options *toml.Primitive `toml:"options" json:"options"` - // PrivilegedWithoutHostDevices overloads the default behaviour for adding host devices to the - // runtime spec when the container is privileged. Defaults to false. - PrivilegedWithoutHostDevices bool `toml:"privileged_without_host_devices" json:"privileged_without_host_devices"` - // BaseRuntimeSpec is a json file with OCI spec to use as base spec that all container's will be created from. - BaseRuntimeSpec string `toml:"base_runtime_spec" json:"baseRuntimeSpec"` -} - -// ContainerdConfig contains toml config related to containerd -type ContainerdConfig struct { - // Snapshotter is the snapshotter used by containerd. - Snapshotter string `toml:"snapshotter" json:"snapshotter"` - // DefaultRuntimeName is the default runtime name to use from the runtimes table. - DefaultRuntimeName string `toml:"default_runtime_name" json:"defaultRuntimeName"` - // DefaultRuntime is the default runtime to use in containerd. - // This runtime is used when no runtime handler (or the empty string) is provided. - // DEPRECATED: use DefaultRuntimeName instead. Remove in containerd 1.4. - DefaultRuntime Runtime `toml:"default_runtime" json:"defaultRuntime"` - // UntrustedWorkloadRuntime is a runtime to run untrusted workloads on it. - // DEPRECATED: use `untrusted` runtime in Runtimes instead. Remove in containerd 1.4. - UntrustedWorkloadRuntime Runtime `toml:"untrusted_workload_runtime" json:"untrustedWorkloadRuntime"` - // Runtimes is a map from CRI RuntimeHandler strings, which specify types of runtime - // configurations, to the matching configurations. - Runtimes map[string]Runtime `toml:"runtimes" json:"runtimes"` - // NoPivot disables pivot-root (linux only), required when running a container in a RamDisk with runc - // This only works for runtime type "io.containerd.runtime.v1.linux". - NoPivot bool `toml:"no_pivot" json:"noPivot"` - - // DisableSnapshotAnnotations disables to pass additional annotations (image - // related information) to snapshotters. These annotations are required by - // stargz snapshotter (https://github.com/containerd/stargz-snapshotter). - DisableSnapshotAnnotations bool `toml:"disable_snapshot_annotations" json:"disableSnapshotAnnotations"` - - // DiscardUnpackedLayers is a boolean flag to specify whether to allow GC to - // remove layers from the content store after successfully unpacking these - // layers to the snapshotter. - DiscardUnpackedLayers bool `toml:"discard_unpacked_layers" json:"discardUnpackedLayers"` -} - -// CniConfig contains toml config related to cni -type CniConfig struct { - // NetworkPluginBinDir is the directory in which the binaries for the plugin is kept. - NetworkPluginBinDir string `toml:"bin_dir" json:"binDir"` - // NetworkPluginConfDir is the directory in which the admin places a CNI conf. - NetworkPluginConfDir string `toml:"conf_dir" json:"confDir"` - // NetworkPluginMaxConfNum is the max number of plugin config files that will - // be loaded from the cni config directory by go-cni. Set the value to 0 to - // load all config files (no arbitrary limit). The legacy default value is 1. - NetworkPluginMaxConfNum int `toml:"max_conf_num" json:"maxConfNum"` - // NetworkPluginConfTemplate is the file path of golang template used to generate - // cni config. - // When it is set, containerd will get cidr(s) from kubelet to replace {{.PodCIDR}}, - // {{.PodCIDRRanges}} or {{.Routes}} in the template, and write the config into - // NetworkPluginConfDir. - // Ideally the cni config should be placed by system admin or cni daemon like calico, - // weaveworks etc. However, there are still users using kubenet - // (https://kubernetes.io/docs/concepts/cluster-administration/network-plugins/#kubenet) - // today, who don't have a cni daemonset in production. NetworkPluginConfTemplate is - // a temporary backward-compatible solution for them. - // TODO(random-liu): Deprecate this option when kubenet is deprecated. - NetworkPluginConfTemplate string `toml:"conf_template" json:"confTemplate"` -} - -// Mirror contains the config related to the registry mirror -type Mirror struct { - // Endpoints are endpoints for a namespace. CRI plugin will try the endpoints - // one by one until a working one is found. The endpoint must be a valid url - // with host specified. - // The scheme, host and path from the endpoint URL will be used. - Endpoints []string `toml:"endpoint" json:"endpoint"` -} - -// AuthConfig contains the config related to authentication to a specific registry -type AuthConfig struct { - // Username is the username to login the registry. - Username string `toml:"username" json:"username"` - // Password is the password to login the registry. - Password string `toml:"password" json:"password"` - // Auth is a base64 encoded string from the concatenation of the username, - // a colon, and the password. - Auth string `toml:"auth" json:"auth"` - // IdentityToken is used to authenticate the user and get - // an access token for the registry. - IdentityToken string `toml:"identitytoken" json:"identitytoken"` -} - -// TLSConfig contains the CA/Cert/Key used for a registry -type TLSConfig struct { - InsecureSkipVerify bool `toml:"insecure_skip_verify" json:"insecure_skip_verify"` - CAFile string `toml:"ca_file" json:"caFile"` - CertFile string `toml:"cert_file" json:"certFile"` - KeyFile string `toml:"key_file" json:"keyFile"` -} - -// Registry is registry settings configured -type Registry struct { - // Mirrors are namespace to mirror mapping for all namespaces. - Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"` - // Configs are configs for each registry. - // The key is the domain name or IP of the registry. - Configs map[string]RegistryConfig `toml:"configs" json:"configs"` - - // Auths are registry endpoint to auth config mapping. The registry endpoint must - // be a valid url with host specified. - // DEPRECATED: Use Configs instead. Remove in containerd 1.4. - Auths map[string]AuthConfig `toml:"auths" json:"auths"` - // Headers adds additional HTTP headers that get sent to all registries - Headers map[string][]string `toml:"headers" json:"headers"` -} - -// RegistryConfig contains configuration used to communicate with the registry. -type RegistryConfig struct { - // Auth contains information to authenticate to the registry. - Auth *AuthConfig `toml:"auth" json:"auth"` - // TLS is a pair of CA/Cert/Key which then are used when creating the transport - // that communicates with the registry. - TLS *TLSConfig `toml:"tls" json:"tls"` -} - -// ImageDecryption contains configuration to handling decryption of encrypted container images. -type ImageDecryption struct { - // KeyModel specifies the trust model of where keys should reside. - // - // Details of field usage can be found in: - // https://github.com/containerd/cri/tree/master/docs/config.md - // - // Details of key models can be found in: - // https://github.com/containerd/cri/tree/master/docs/decryption.md - KeyModel string `toml:"key_model" json:"keyModel"` -} - -// PluginConfig contains toml config related to CRI plugin, -// it is a subset of Config. -type PluginConfig struct { - // ContainerdConfig contains config related to containerd - ContainerdConfig `toml:"containerd" json:"containerd"` - // CniConfig contains config related to cni - CniConfig `toml:"cni" json:"cni"` - // Registry contains config related to the registry - Registry Registry `toml:"registry" json:"registry"` - // ImageDecryption contains config related to handling decryption of encrypted container images - ImageDecryption `toml:"image_decryption" json:"imageDecryption"` - // DisableTCPService disables serving CRI on the TCP server. - DisableTCPService bool `toml:"disable_tcp_service" json:"disableTCPService"` - // StreamServerAddress is the ip address streaming server is listening on. - StreamServerAddress string `toml:"stream_server_address" json:"streamServerAddress"` - // StreamServerPort is the port streaming server is listening on. - StreamServerPort string `toml:"stream_server_port" json:"streamServerPort"` - // StreamIdleTimeout is the maximum time a streaming connection - // can be idle before the connection is automatically closed. - // The string is in the golang duration format, see: - // https://golang.org/pkg/time/#ParseDuration - StreamIdleTimeout string `toml:"stream_idle_timeout" json:"streamIdleTimeout"` - // EnableSelinux indicates to enable the selinux support. - EnableSelinux bool `toml:"enable_selinux" json:"enableSelinux"` - // SelinuxCategoryRange allows the upper bound on the category range to be set. - // If not specified or set to 0, defaults to 1024 from the selinux package. - SelinuxCategoryRange int `toml:"selinux_category_range" json:"selinuxCategoryRange"` - // SandboxImage is the image used by sandbox container. - SandboxImage string `toml:"sandbox_image" json:"sandboxImage"` - // StatsCollectPeriod is the period (in seconds) of snapshots stats collection. - StatsCollectPeriod int `toml:"stats_collect_period" json:"statsCollectPeriod"` - // SystemdCgroup enables systemd cgroup support. - // This only works for runtime type "io.containerd.runtime.v1.linux". - // DEPRECATED: config runc runtime handler instead. Remove when shim v1 is deprecated. - SystemdCgroup bool `toml:"systemd_cgroup" json:"systemdCgroup"` - // EnableTLSStreaming indicates to enable the TLS streaming support. - EnableTLSStreaming bool `toml:"enable_tls_streaming" json:"enableTLSStreaming"` - // X509KeyPairStreaming is a x509 key pair used for TLS streaming - X509KeyPairStreaming `toml:"x509_key_pair_streaming" json:"x509KeyPairStreaming"` - // MaxContainerLogLineSize is the maximum log line size in bytes for a container. - // Log line longer than the limit will be split into multiple lines. Non-positive - // value means no limit. - MaxContainerLogLineSize int `toml:"max_container_log_line_size" json:"maxContainerLogSize"` - // DisableCgroup indicates to disable the cgroup support. - // This is useful when the containerd does not have permission to access cgroup. - DisableCgroup bool `toml:"disable_cgroup" json:"disableCgroup"` - // DisableApparmor indicates to disable the apparmor support. - // This is useful when the containerd does not have permission to access Apparmor. - DisableApparmor bool `toml:"disable_apparmor" json:"disableApparmor"` - // RestrictOOMScoreAdj indicates to limit the lower bound of OOMScoreAdj to the containerd's - // current OOMScoreADj. - // This is useful when the containerd does not have permission to decrease OOMScoreAdj. - RestrictOOMScoreAdj bool `toml:"restrict_oom_score_adj" json:"restrictOOMScoreAdj"` - // MaxConcurrentDownloads restricts the number of concurrent downloads for each image. - MaxConcurrentDownloads int `toml:"max_concurrent_downloads" json:"maxConcurrentDownloads"` - // DisableProcMount disables Kubernetes ProcMount support. This MUST be set to `true` - // when using containerd with Kubernetes <=1.11. - DisableProcMount bool `toml:"disable_proc_mount" json:"disableProcMount"` - // UnsetSeccompProfile is the profile containerd/cri will use If the provided seccomp profile is - // unset (`""`) for a container (default is `unconfined`) - UnsetSeccompProfile string `toml:"unset_seccomp_profile" json:"unsetSeccompProfile"` - // TolerateMissingHugetlbController if set to false will error out on create/update - // container requests with huge page limits if the cgroup controller for hugepages is not present. - // This helps with supporting Kubernetes <=1.18 out of the box. (default is `true`) - TolerateMissingHugetlbController bool `toml:"tolerate_missing_hugetlb_controller" json:"tolerateMissingHugetlbController"` - // DisableHugetlbController indicates to silently disable the hugetlb controller, even when it is - // present in /sys/fs/cgroup/cgroup.controllers. - // This helps with running rootless mode + cgroup v2 + systemd but without hugetlb delegation. - DisableHugetlbController bool `toml:"disable_hugetlb_controller" json:"disableHugetlbController"` - // IgnoreImageDefinedVolumes ignores volumes defined by the image. Useful for better resource - // isolation, security and early detection of issues in the mount configuration when using - // ReadOnlyRootFilesystem since containers won't silently mount a temporary volume. - IgnoreImageDefinedVolumes bool `toml:"ignore_image_defined_volumes" json:"ignoreImageDefinedVolumes"` -} - -// X509KeyPairStreaming contains the x509 configuration for streaming -type X509KeyPairStreaming struct { - // TLSCertFile is the path to a certificate file - TLSCertFile string `toml:"tls_cert_file" json:"tlsCertFile"` - // TLSKeyFile is the path to a private key file - TLSKeyFile string `toml:"tls_key_file" json:"tlsKeyFile"` -} - -// Config contains all configurations for cri server. -type Config struct { - // PluginConfig is the config for CRI plugin. - PluginConfig - // ContainerdRootDir is the root directory path for containerd. - ContainerdRootDir string `json:"containerdRootDir"` - // ContainerdEndpoint is the containerd endpoint path. - ContainerdEndpoint string `json:"containerdEndpoint"` - // RootDir is the root directory path for managing cri plugin files - // (metadata checkpoint etc.) - RootDir string `json:"rootDir"` - // StateDir is the root directory path for managing volatile pod/container data - StateDir string `json:"stateDir"` -} - -const ( - // RuntimeUntrusted is the implicit runtime defined for ContainerdConfig.UntrustedWorkloadRuntime - RuntimeUntrusted = "untrusted" - // RuntimeDefault is the implicit runtime defined for ContainerdConfig.DefaultRuntime - RuntimeDefault = "default" - // KeyModelNode is the key model where key for encrypted images reside - // on the worker nodes - KeyModelNode = "node" -) - -// ValidatePluginConfig validates the given plugin configuration. -func ValidatePluginConfig(ctx context.Context, c *PluginConfig) error { - if c.ContainerdConfig.Runtimes == nil { - c.ContainerdConfig.Runtimes = make(map[string]Runtime) - } - - // Validation for deprecated untrusted_workload_runtime. - if c.ContainerdConfig.UntrustedWorkloadRuntime.Type != "" { - log.G(ctx).Warning("`untrusted_workload_runtime` is deprecated, please use `untrusted` runtime in `runtimes` instead") - if _, ok := c.ContainerdConfig.Runtimes[RuntimeUntrusted]; ok { - return errors.Errorf("conflicting definitions: configuration includes both `untrusted_workload_runtime` and `runtimes[%q]`", RuntimeUntrusted) - } - c.ContainerdConfig.Runtimes[RuntimeUntrusted] = c.ContainerdConfig.UntrustedWorkloadRuntime - } - - // Validation for deprecated default_runtime field. - if c.ContainerdConfig.DefaultRuntime.Type != "" { - log.G(ctx).Warning("`default_runtime` is deprecated, please use `default_runtime_name` to reference the default configuration you have defined in `runtimes`") - c.ContainerdConfig.DefaultRuntimeName = RuntimeDefault - c.ContainerdConfig.Runtimes[RuntimeDefault] = c.ContainerdConfig.DefaultRuntime - } - - // Validation for default_runtime_name - if c.ContainerdConfig.DefaultRuntimeName == "" { - return errors.New("`default_runtime_name` is empty") - } - if _, ok := c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName]; !ok { - return errors.New("no corresponding runtime configured in `runtimes` for `default_runtime_name`") - } - - // Validation for deprecated runtime options. - if c.SystemdCgroup { - if c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName].Type != plugin.RuntimeLinuxV1 { - return errors.Errorf("`systemd_cgroup` only works for runtime %s", plugin.RuntimeLinuxV1) - } - log.G(ctx).Warning("`systemd_cgroup` is deprecated, please use runtime `options` instead") - } - if c.NoPivot { - if c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName].Type != plugin.RuntimeLinuxV1 { - return errors.Errorf("`no_pivot` only works for runtime %s", plugin.RuntimeLinuxV1) - } - // NoPivot can't be deprecated yet, because there is no alternative config option - // for `io.containerd.runtime.v1.linux`. - } - for _, r := range c.ContainerdConfig.Runtimes { - if r.Engine != "" { - if r.Type != plugin.RuntimeLinuxV1 { - return errors.Errorf("`runtime_engine` only works for runtime %s", plugin.RuntimeLinuxV1) - } - log.G(ctx).Warning("`runtime_engine` is deprecated, please use runtime `options` instead") - } - if r.Root != "" { - if r.Type != plugin.RuntimeLinuxV1 { - return errors.Errorf("`runtime_root` only works for runtime %s", plugin.RuntimeLinuxV1) - } - log.G(ctx).Warning("`runtime_root` is deprecated, please use runtime `options` instead") - } - } - - // Validation for deprecated auths options and mapping it to configs. - if len(c.Registry.Auths) != 0 { - if c.Registry.Configs == nil { - c.Registry.Configs = make(map[string]RegistryConfig) - } - for endpoint, auth := range c.Registry.Auths { - config := c.Registry.Configs[endpoint] - config.Auth = &auth - c.Registry.Configs[endpoint] = config - } - log.G(ctx).Warning("`auths` is deprecated, please use registry`configs` instead") - } - - // Validation for stream_idle_timeout - if c.StreamIdleTimeout != "" { - if _, err := time.ParseDuration(c.StreamIdleTimeout); err != nil { - return errors.Wrap(err, "invalid stream idle timeout") - } - } - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/config/config_unix.go b/vendor/github.com/containerd/cri/pkg/config/config_unix.go deleted file mode 100644 index 9df456b53..000000000 --- a/vendor/github.com/containerd/cri/pkg/config/config_unix.go +++ /dev/null @@ -1,75 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package config - -import ( - "github.com/BurntSushi/toml" - "github.com/containerd/containerd" - "github.com/containerd/cri/pkg/streaming" -) - -// DefaultConfig returns default configurations of cri plugin. -func DefaultConfig() PluginConfig { - return PluginConfig{ - CniConfig: CniConfig{ - NetworkPluginBinDir: "/opt/cni/bin", - NetworkPluginConfDir: "/etc/cni/net.d", - NetworkPluginMaxConfNum: 1, // only one CNI plugin config file will be loaded - NetworkPluginConfTemplate: "", - }, - ContainerdConfig: ContainerdConfig{ - Snapshotter: containerd.DefaultSnapshotter, - DefaultRuntimeName: "runc", - NoPivot: false, - Runtimes: map[string]Runtime{ - "runc": { - Type: "io.containerd.runc.v2", - Options: new(toml.Primitive), - }, - }, - }, - DisableTCPService: true, - StreamServerAddress: "127.0.0.1", - StreamServerPort: "0", - StreamIdleTimeout: streaming.DefaultConfig.StreamIdleTimeout.String(), // 4 hour - EnableSelinux: false, - SelinuxCategoryRange: 1024, - EnableTLSStreaming: false, - X509KeyPairStreaming: X509KeyPairStreaming{ - TLSKeyFile: "", - TLSCertFile: "", - }, - SandboxImage: "k8s.gcr.io/pause:3.2", - StatsCollectPeriod: 10, - SystemdCgroup: false, - MaxContainerLogLineSize: 16 * 1024, - Registry: Registry{ - Mirrors: map[string]Mirror{ - "docker.io": { - Endpoints: []string{"https://registry-1.docker.io"}, - }, - }, - }, - MaxConcurrentDownloads: 3, - DisableProcMount: false, - TolerateMissingHugetlbController: true, - DisableHugetlbController: true, - IgnoreImageDefinedVolumes: false, - } -} diff --git a/vendor/github.com/containerd/cri/pkg/config/config_windows.go b/vendor/github.com/containerd/cri/pkg/config/config_windows.go deleted file mode 100644 index d559b4160..000000000 --- a/vendor/github.com/containerd/cri/pkg/config/config_windows.go +++ /dev/null @@ -1,71 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package config - -import ( - "os" - "path/filepath" - - "github.com/containerd/containerd" - "github.com/containerd/cri/pkg/streaming" -) - -// DefaultConfig returns default configurations of cri plugin. -func DefaultConfig() PluginConfig { - return PluginConfig{ - CniConfig: CniConfig{ - NetworkPluginBinDir: filepath.Join(os.Getenv("ProgramFiles"), "containerd", "cni", "bin"), - NetworkPluginConfDir: filepath.Join(os.Getenv("ProgramFiles"), "containerd", "cni", "conf"), - NetworkPluginMaxConfNum: 1, - NetworkPluginConfTemplate: "", - }, - ContainerdConfig: ContainerdConfig{ - Snapshotter: containerd.DefaultSnapshotter, - DefaultRuntimeName: "runhcs-wcow-process", - NoPivot: false, - Runtimes: map[string]Runtime{ - "runhcs-wcow-process": { - Type: "io.containerd.runhcs.v1", - }, - }, - }, - DisableTCPService: true, - StreamServerAddress: "127.0.0.1", - StreamServerPort: "0", - StreamIdleTimeout: streaming.DefaultConfig.StreamIdleTimeout.String(), // 4 hour - EnableTLSStreaming: false, - X509KeyPairStreaming: X509KeyPairStreaming{ - TLSKeyFile: "", - TLSCertFile: "", - }, - SandboxImage: "mcr.microsoft.com/oss/kubernetes/pause:1.4.0", - StatsCollectPeriod: 10, - MaxContainerLogLineSize: 16 * 1024, - Registry: Registry{ - Mirrors: map[string]Mirror{ - "docker.io": { - Endpoints: []string{"https://registry-1.docker.io"}, - }, - }, - }, - MaxConcurrentDownloads: 3, - IgnoreImageDefinedVolumes: false, - // TODO(windows): Add platform specific config, so that most common defaults can be shared. - } -} diff --git a/vendor/github.com/containerd/cri/pkg/constants/constants.go b/vendor/github.com/containerd/cri/pkg/constants/constants.go deleted file mode 100644 index b38221502..000000000 --- a/vendor/github.com/containerd/cri/pkg/constants/constants.go +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package constants - -// TODO(random-liu): Merge annotations package into this package. - -const ( - // K8sContainerdNamespace is the namespace we use to connect containerd. - K8sContainerdNamespace = "k8s.io" - // CRIVersion is the CRI version supported by the CRI plugin. - CRIVersion = "v1alpha2" -) diff --git a/vendor/github.com/containerd/cri/pkg/containerd/opts/container.go b/vendor/github.com/containerd/cri/pkg/containerd/opts/container.go deleted file mode 100644 index fe199d5fb..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/opts/container.go +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package opts - -import ( - "context" - "io/ioutil" - "os" - "path/filepath" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/mount" - "github.com/containerd/continuity/fs" - "github.com/pkg/errors" -) - -// WithNewSnapshot wraps `containerd.WithNewSnapshot` so that if creating the -// snapshot fails we make sure the image is actually unpacked and and retry. -func WithNewSnapshot(id string, i containerd.Image) containerd.NewContainerOpts { - f := containerd.WithNewSnapshot(id, i) - return func(ctx context.Context, client *containerd.Client, c *containers.Container) error { - if err := f(ctx, client, c); err != nil { - if !errdefs.IsNotFound(err) { - return err - } - - if err := i.Unpack(ctx, c.Snapshotter); err != nil { - return errors.Wrap(err, "error unpacking image") - } - return f(ctx, client, c) - } - return nil - } -} - -// WithVolumes copies ownership of volume in rootfs to its corresponding host path. -// It doesn't update runtime spec. -// The passed in map is a host path to container path map for all volumes. -func WithVolumes(volumeMounts map[string]string) containerd.NewContainerOpts { - return func(ctx context.Context, client *containerd.Client, c *containers.Container) (err error) { - if c.Snapshotter == "" { - return errors.New("no snapshotter set for container") - } - if c.SnapshotKey == "" { - return errors.New("rootfs not created for container") - } - snapshotter := client.SnapshotService(c.Snapshotter) - mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) - if err != nil { - return err - } - root, err := ioutil.TempDir("", "ctd-volume") - if err != nil { - return err - } - // We change RemoveAll to Remove so that we either leak a temp dir - // if it fails but not RM snapshot data. - // refer to https://github.com/containerd/containerd/pull/1868 - // https://github.com/containerd/containerd/pull/1785 - defer os.Remove(root) // nolint: errcheck - if err := mount.All(mounts, root); err != nil { - return errors.Wrap(err, "failed to mount") - } - defer func() { - if uerr := mount.Unmount(root, 0); uerr != nil { - log.G(ctx).WithError(uerr).Errorf("Failed to unmount snapshot %q", c.SnapshotKey) - if err == nil { - err = uerr - } - } - }() - - for host, volume := range volumeMounts { - src := filepath.Join(root, volume) - if _, err := os.Stat(src); err != nil { - if os.IsNotExist(err) { - // Skip copying directory if it does not exist. - continue - } - return errors.Wrap(err, "stat volume in rootfs") - } - if err := copyExistingContents(src, host); err != nil { - return errors.Wrap(err, "taking runtime copy of volume") - } - } - return nil - } -} - -// copyExistingContents copies from the source to the destination and -// ensures the ownership is appropriately set. -func copyExistingContents(source, destination string) error { - dstList, err := ioutil.ReadDir(destination) - if err != nil { - return err - } - if len(dstList) != 0 { - return errors.Errorf("volume at %q is not initially empty", destination) - } - return fs.CopyDir(destination, source) -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go b/vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go deleted file mode 100644 index 1afb4fc1a..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go +++ /dev/null @@ -1,113 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package opts - -import ( - "context" - "os" - "path/filepath" - "strings" - - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" - - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// DefaultSandboxCPUshares is default cpu shares for sandbox container. -// TODO(windows): Revisit cpu shares for windows (https://github.com/containerd/cri/issues/1297) -const DefaultSandboxCPUshares = 2 - -// WithRelativeRoot sets the root for the container -func WithRelativeRoot(root string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) { - if s.Root == nil { - s.Root = &runtimespec.Root{} - } - s.Root.Path = root - return nil - } -} - -// WithoutRoot sets the root to nil for the container. -func WithoutRoot(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - s.Root = nil - return nil -} - -// WithProcessArgs sets the process args on the spec based on the image and runtime config -func WithProcessArgs(config *runtime.ContainerConfig, image *imagespec.ImageConfig) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) { - command, args := config.GetCommand(), config.GetArgs() - // The following logic is migrated from https://github.com/moby/moby/blob/master/daemon/commit.go - // TODO(random-liu): Clearly define the commands overwrite behavior. - if len(command) == 0 { - // Copy array to avoid data race. - if len(args) == 0 { - args = append([]string{}, image.Cmd...) - } - if command == nil { - command = append([]string{}, image.Entrypoint...) - } - } - if len(command) == 0 && len(args) == 0 { - return errors.New("no command specified") - } - return oci.WithProcessArgs(append(command, args...)...)(ctx, client, c, s) - } -} - -// mounts defines how to sort runtime.Mount. -// This is the same with the Docker implementation: -// https://github.com/moby/moby/blob/17.05.x/daemon/volumes.go#L26 -type orderedMounts []*runtime.Mount - -// Len returns the number of mounts. Used in sorting. -func (m orderedMounts) Len() int { - return len(m) -} - -// Less returns true if the number of parts (a/b/c would be 3 parts) in the -// mount indexed by parameter 1 is less than that of the mount indexed by -// parameter 2. Used in sorting. -func (m orderedMounts) Less(i, j int) bool { - return m.parts(i) < m.parts(j) -} - -// Swap swaps two items in an array of mounts. Used in sorting -func (m orderedMounts) Swap(i, j int) { - m[i], m[j] = m[j], m[i] -} - -// parts returns the number of parts in the destination of a mount. Used in sorting. -func (m orderedMounts) parts(i int) int { - return strings.Count(filepath.Clean(m[i].ContainerPath), string(os.PathSeparator)) -} - -// WithAnnotation sets the provided annotation -func WithAnnotation(k, v string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Annotations == nil { - s.Annotations = make(map[string]string) - } - s.Annotations[k] = v - return nil - } -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/opts/spec_unix.go b/vendor/github.com/containerd/cri/pkg/containerd/opts/spec_unix.go deleted file mode 100644 index d644962d5..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/opts/spec_unix.go +++ /dev/null @@ -1,721 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package opts - -import ( - "context" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strconv" - "strings" - "sync" - "syscall" - - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/oci" - "github.com/opencontainers/runc/libcontainer/devices" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - osinterface "github.com/containerd/cri/pkg/os" - "github.com/containerd/cri/pkg/util" -) - -// WithAdditionalGIDs adds any additional groups listed for a particular user in the -// /etc/groups file of the image's root filesystem to the OCI spec's additionalGids array. -func WithAdditionalGIDs(userstr string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) { - if s.Process == nil { - s.Process = &runtimespec.Process{} - } - gids := s.Process.User.AdditionalGids - if err := oci.WithAdditionalGIDs(userstr)(ctx, client, c, s); err != nil { - return err - } - // Merge existing gids and new gids. - s.Process.User.AdditionalGids = mergeGids(s.Process.User.AdditionalGids, gids) - return nil - } -} - -func mergeGids(gids1, gids2 []uint32) []uint32 { - gidsMap := make(map[uint32]struct{}) - for _, gid1 := range gids1 { - gidsMap[gid1] = struct{}{} - } - for _, gid2 := range gids2 { - gidsMap[gid2] = struct{}{} - } - var gids []uint32 - for gid := range gidsMap { - gids = append(gids, gid) - } - sort.Slice(gids, func(i, j int) bool { return gids[i] < gids[j] }) - return gids -} - -// WithoutRunMount removes the `/run` inside the spec -func WithoutRunMount(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error { - var ( - mounts []runtimespec.Mount - current = s.Mounts - ) - for _, m := range current { - if filepath.Clean(m.Destination) == "/run" { - continue - } - mounts = append(mounts, m) - } - s.Mounts = mounts - return nil -} - -// WithoutDefaultSecuritySettings removes the default security settings generated on a spec -func WithoutDefaultSecuritySettings(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Process == nil { - s.Process = &runtimespec.Process{} - } - // Make sure no default seccomp/apparmor is specified - s.Process.ApparmorProfile = "" - if s.Linux != nil { - s.Linux.Seccomp = nil - } - // Remove default rlimits (See issue #515) - s.Process.Rlimits = nil - return nil -} - -// WithMounts sorts and adds runtime and CRI mounts to the spec -func WithMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*runtime.Mount, mountLabel string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, _ *containers.Container, s *runtimespec.Spec) (err error) { - // mergeMounts merge CRI mounts with extra mounts. If a mount destination - // is mounted by both a CRI mount and an extra mount, the CRI mount will - // be kept. - var ( - criMounts = config.GetMounts() - mounts = append([]*runtime.Mount{}, criMounts...) - ) - // Copy all mounts from extra mounts, except for mounts overridden by CRI. - for _, e := range extra { - found := false - for _, c := range criMounts { - if filepath.Clean(e.ContainerPath) == filepath.Clean(c.ContainerPath) { - found = true - break - } - } - if !found { - mounts = append(mounts, e) - } - } - - // Sort mounts in number of parts. This ensures that high level mounts don't - // shadow other mounts. - sort.Sort(orderedMounts(mounts)) - - // Mount cgroup into the container as readonly, which inherits docker's behavior. - s.Mounts = append(s.Mounts, runtimespec.Mount{ - Source: "cgroup", - Destination: "/sys/fs/cgroup", - Type: "cgroup", - Options: []string{"nosuid", "noexec", "nodev", "relatime", "ro"}, - }) - - // Copy all mounts from default mounts, except for - // - mounts overridden by supplied mount; - // - all mounts under /dev if a supplied /dev is present. - mountSet := make(map[string]struct{}) - for _, m := range mounts { - mountSet[filepath.Clean(m.ContainerPath)] = struct{}{} - } - - defaultMounts := s.Mounts - s.Mounts = nil - - for _, m := range defaultMounts { - dst := filepath.Clean(m.Destination) - if _, ok := mountSet[dst]; ok { - // filter out mount overridden by a supplied mount - continue - } - if _, mountDev := mountSet["/dev"]; mountDev && strings.HasPrefix(dst, "/dev/") { - // filter out everything under /dev if /dev is a supplied mount - continue - } - s.Mounts = append(s.Mounts, m) - } - - for _, mount := range mounts { - var ( - dst = mount.GetContainerPath() - src = mount.GetHostPath() - ) - // Create the host path if it doesn't exist. - // TODO(random-liu): Add CRI validation test for this case. - if _, err := osi.Stat(src); err != nil { - if !os.IsNotExist(err) { - return errors.Wrapf(err, "failed to stat %q", src) - } - if err := osi.MkdirAll(src, 0755); err != nil { - return errors.Wrapf(err, "failed to mkdir %q", src) - } - } - // TODO(random-liu): Add cri-containerd integration test or cri validation test - // for this. - src, err := osi.ResolveSymbolicLink(src) - if err != nil { - return errors.Wrapf(err, "failed to resolve symlink %q", src) - } - if s.Linux == nil { - s.Linux = &runtimespec.Linux{} - } - options := []string{"rbind"} - switch mount.GetPropagation() { - case runtime.MountPropagation_PROPAGATION_PRIVATE: - options = append(options, "rprivate") - // Since default root propagation in runc is rprivate ignore - // setting the root propagation - case runtime.MountPropagation_PROPAGATION_BIDIRECTIONAL: - if err := ensureShared(src, osi.(osinterface.UNIX).LookupMount); err != nil { - return err - } - options = append(options, "rshared") - s.Linux.RootfsPropagation = "rshared" - case runtime.MountPropagation_PROPAGATION_HOST_TO_CONTAINER: - if err := ensureSharedOrSlave(src, osi.(osinterface.UNIX).LookupMount); err != nil { - return err - } - options = append(options, "rslave") - if s.Linux.RootfsPropagation != "rshared" && - s.Linux.RootfsPropagation != "rslave" { - s.Linux.RootfsPropagation = "rslave" - } - default: - log.G(ctx).Warnf("Unknown propagation mode for hostPath %q", mount.HostPath) - options = append(options, "rprivate") - } - - // NOTE(random-liu): we don't change all mounts to `ro` when root filesystem - // is readonly. This is different from docker's behavior, but make more sense. - if mount.GetReadonly() { - options = append(options, "ro") - } else { - options = append(options, "rw") - } - - if mount.GetSelinuxRelabel() { - if err := label.Relabel(src, mountLabel, false); err != nil && err != unix.ENOTSUP { - return errors.Wrapf(err, "relabel %q with %q failed", src, mountLabel) - } - } - s.Mounts = append(s.Mounts, runtimespec.Mount{ - Source: src, - Destination: dst, - Type: "bind", - Options: options, - }) - } - return nil - } -} - -// Ensure mount point on which path is mounted, is shared. -func ensureShared(path string, lookupMount func(string) (mount.Info, error)) error { - mountInfo, err := lookupMount(path) - if err != nil { - return err - } - - // Make sure source mount point is shared. - optsSplit := strings.Split(mountInfo.Optional, " ") - for _, opt := range optsSplit { - if strings.HasPrefix(opt, "shared:") { - return nil - } - } - - return errors.Errorf("path %q is mounted on %q but it is not a shared mount", path, mountInfo.Mountpoint) -} - -// ensure mount point on which path is mounted, is either shared or slave. -func ensureSharedOrSlave(path string, lookupMount func(string) (mount.Info, error)) error { - mountInfo, err := lookupMount(path) - if err != nil { - return err - } - // Make sure source mount point is shared. - optsSplit := strings.Split(mountInfo.Optional, " ") - for _, opt := range optsSplit { - if strings.HasPrefix(opt, "shared:") { - return nil - } else if strings.HasPrefix(opt, "master:") { - return nil - } - } - return errors.Errorf("path %q is mounted on %q but it is not a shared or slave mount", path, mountInfo.Mountpoint) -} - -func addDevice(s *runtimespec.Spec, rd runtimespec.LinuxDevice) { - for i, dev := range s.Linux.Devices { - if dev.Path == rd.Path { - s.Linux.Devices[i] = rd - return - } - } - s.Linux.Devices = append(s.Linux.Devices, rd) -} - -// WithDevices sets the provided devices onto the container spec -func WithDevices(osi osinterface.OS, config *runtime.ContainerConfig) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) { - if s.Linux == nil { - s.Linux = &runtimespec.Linux{} - } - if s.Linux.Resources == nil { - s.Linux.Resources = &runtimespec.LinuxResources{} - } - for _, device := range config.GetDevices() { - path, err := osi.ResolveSymbolicLink(device.HostPath) - if err != nil { - return err - } - dev, err := devices.DeviceFromPath(path, device.Permissions) - if err != nil { - return err - } - rd := runtimespec.LinuxDevice{ - Path: device.ContainerPath, - Type: string(dev.Type), - Major: dev.Major, - Minor: dev.Minor, - UID: &dev.Uid, - GID: &dev.Gid, - } - - addDevice(s, rd) - - s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, runtimespec.LinuxDeviceCgroup{ - Allow: true, - Type: string(dev.Type), - Major: &dev.Major, - Minor: &dev.Minor, - Access: string(dev.Permissions), - }) - } - return nil - } -} - -// WithCapabilities sets the provided capabilties from the security context -func WithCapabilities(sc *runtime.LinuxContainerSecurityContext) oci.SpecOpts { - capabilities := sc.GetCapabilities() - if capabilities == nil { - return nullOpt - } - - var opts []oci.SpecOpts - // Add/drop all capabilities if "all" is specified, so that - // following individual add/drop could still work. E.g. - // AddCapabilities: []string{"ALL"}, DropCapabilities: []string{"CHOWN"} - // will be all capabilities without `CAP_CHOWN`. - if util.InStringSlice(capabilities.GetAddCapabilities(), "ALL") { - opts = append(opts, oci.WithAllCapabilities) - } - if util.InStringSlice(capabilities.GetDropCapabilities(), "ALL") { - opts = append(opts, oci.WithCapabilities(nil)) - } - - var caps []string - for _, c := range capabilities.GetAddCapabilities() { - if strings.ToUpper(c) == "ALL" { - continue - } - // Capabilities in CRI doesn't have `CAP_` prefix, so add it. - caps = append(caps, "CAP_"+strings.ToUpper(c)) - } - opts = append(opts, oci.WithAddedCapabilities(caps)) - - caps = []string{} - for _, c := range capabilities.GetDropCapabilities() { - if strings.ToUpper(c) == "ALL" { - continue - } - caps = append(caps, "CAP_"+strings.ToUpper(c)) - } - opts = append(opts, oci.WithDroppedCapabilities(caps)) - return oci.Compose(opts...) -} - -// WithoutAmbientCaps removes the ambient caps from the spec -func WithoutAmbientCaps(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Process == nil { - s.Process = &runtimespec.Process{} - } - if s.Process.Capabilities == nil { - s.Process.Capabilities = &runtimespec.LinuxCapabilities{} - } - s.Process.Capabilities.Ambient = nil - return nil -} - -// WithDisabledCgroups clears the Cgroups Path from the spec -func WithDisabledCgroups(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Linux == nil { - s.Linux = &runtimespec.Linux{} - } - s.Linux.CgroupsPath = "" - return nil -} - -// WithSelinuxLabels sets the mount and process labels -func WithSelinuxLabels(process, mount string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) { - if s.Linux == nil { - s.Linux = &runtimespec.Linux{} - } - if s.Process == nil { - s.Process = &runtimespec.Process{} - } - s.Linux.MountLabel = mount - s.Process.SelinuxLabel = process - return nil - } -} - -// WithResources sets the provided resource restrictions -func WithResources(resources *runtime.LinuxContainerResources, tolerateMissingHugetlbController, disableHugetlbController bool) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) { - if resources == nil { - return nil - } - if s.Linux == nil { - s.Linux = &runtimespec.Linux{} - } - if s.Linux.Resources == nil { - s.Linux.Resources = &runtimespec.LinuxResources{} - } - if s.Linux.Resources.CPU == nil { - s.Linux.Resources.CPU = &runtimespec.LinuxCPU{} - } - if s.Linux.Resources.Memory == nil { - s.Linux.Resources.Memory = &runtimespec.LinuxMemory{} - } - var ( - p = uint64(resources.GetCpuPeriod()) - q = resources.GetCpuQuota() - shares = uint64(resources.GetCpuShares()) - limit = resources.GetMemoryLimitInBytes() - hugepages = resources.GetHugepageLimits() - ) - - if p != 0 { - s.Linux.Resources.CPU.Period = &p - } - if q != 0 { - s.Linux.Resources.CPU.Quota = &q - } - if shares != 0 { - s.Linux.Resources.CPU.Shares = &shares - } - if cpus := resources.GetCpusetCpus(); cpus != "" { - s.Linux.Resources.CPU.Cpus = cpus - } - if mems := resources.GetCpusetMems(); mems != "" { - s.Linux.Resources.CPU.Mems = resources.GetCpusetMems() - } - if limit != 0 { - s.Linux.Resources.Memory.Limit = &limit - } - if !disableHugetlbController { - if isHugetlbControllerPresent() { - for _, limit := range hugepages { - s.Linux.Resources.HugepageLimits = append(s.Linux.Resources.HugepageLimits, runtimespec.LinuxHugepageLimit{ - Pagesize: limit.PageSize, - Limit: limit.Limit, - }) - } - } else { - if !tolerateMissingHugetlbController { - return errors.Errorf("huge pages limits are specified but hugetlb cgroup controller is missing. " + - "Please set tolerate_missing_hugetlb_controller to `true` to ignore this error") - } - logrus.Warn("hugetlb cgroup controller is absent. skipping huge pages limits") - } - } - return nil - } -} - -var ( - supportsHugetlbOnce sync.Once - supportsHugetlb bool -) - -func isHugetlbControllerPresent() bool { - supportsHugetlbOnce.Do(func() { - supportsHugetlb = false - if IsCgroup2UnifiedMode() { - supportsHugetlb, _ = cgroupv2HasHugetlb() - } else { - supportsHugetlb, _ = cgroupv1HasHugetlb() - } - }) - return supportsHugetlb -} - -var ( - _cgroupv1HasHugetlbOnce sync.Once - _cgroupv1HasHugetlb bool - _cgroupv1HasHugetlbErr error - _cgroupv2HasHugetlbOnce sync.Once - _cgroupv2HasHugetlb bool - _cgroupv2HasHugetlbErr error - isUnifiedOnce sync.Once - isUnified bool -) - -// cgroupv1HasHugetlb returns whether the hugetlb controller is present on -// cgroup v1. -func cgroupv1HasHugetlb() (bool, error) { - _cgroupv1HasHugetlbOnce.Do(func() { - if _, err := ioutil.ReadDir("/sys/fs/cgroup/hugetlb"); err != nil { - _cgroupv1HasHugetlbErr = errors.Wrap(err, "readdir /sys/fs/cgroup/hugetlb") - _cgroupv1HasHugetlb = false - } else { - _cgroupv1HasHugetlbErr = nil - _cgroupv1HasHugetlb = true - } - }) - return _cgroupv1HasHugetlb, _cgroupv1HasHugetlbErr -} - -// cgroupv2HasHugetlb returns whether the hugetlb controller is present on -// cgroup v2. -func cgroupv2HasHugetlb() (bool, error) { - _cgroupv2HasHugetlbOnce.Do(func() { - controllers, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers") - if err != nil { - _cgroupv2HasHugetlbErr = errors.Wrap(err, "read /sys/fs/cgroup/cgroup.controllers") - return - } - _cgroupv2HasHugetlb = strings.Contains(string(controllers), "hugetlb") - }) - return _cgroupv2HasHugetlb, _cgroupv2HasHugetlbErr -} - -// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode. -func IsCgroup2UnifiedMode() bool { - isUnifiedOnce.Do(func() { - var st syscall.Statfs_t - if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil { - panic("cannot statfs cgroup root") - } - isUnified = st.Type == unix.CGROUP2_SUPER_MAGIC - }) - return isUnified -} - -// WithOOMScoreAdj sets the oom score -func WithOOMScoreAdj(config *runtime.ContainerConfig, restrict bool) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Process == nil { - s.Process = &runtimespec.Process{} - } - - resources := config.GetLinux().GetResources() - if resources == nil { - return nil - } - adj := int(resources.GetOomScoreAdj()) - if restrict { - var err error - adj, err = restrictOOMScoreAdj(adj) - if err != nil { - return err - } - } - s.Process.OOMScoreAdj = &adj - return nil - } -} - -// WithSysctls sets the provided sysctls onto the spec -func WithSysctls(sysctls map[string]string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Linux == nil { - s.Linux = &runtimespec.Linux{} - } - if s.Linux.Sysctl == nil { - s.Linux.Sysctl = make(map[string]string) - } - for k, v := range sysctls { - s.Linux.Sysctl[k] = v - } - return nil - } -} - -// WithPodOOMScoreAdj sets the oom score for the pod sandbox -func WithPodOOMScoreAdj(adj int, restrict bool) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Process == nil { - s.Process = &runtimespec.Process{} - } - if restrict { - var err error - adj, err = restrictOOMScoreAdj(adj) - if err != nil { - return err - } - } - s.Process.OOMScoreAdj = &adj - return nil - } -} - -// WithSupplementalGroups sets the supplemental groups for the process -func WithSupplementalGroups(groups []int64) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Process == nil { - s.Process = &runtimespec.Process{} - } - var guids []uint32 - for _, g := range groups { - guids = append(guids, uint32(g)) - } - s.Process.User.AdditionalGids = mergeGids(s.Process.User.AdditionalGids, guids) - return nil - } -} - -// WithPodNamespaces sets the pod namespaces for the container -func WithPodNamespaces(config *runtime.LinuxContainerSecurityContext, pid uint32) oci.SpecOpts { - namespaces := config.GetNamespaceOptions() - - opts := []oci.SpecOpts{ - oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.NetworkNamespace, Path: GetNetworkNamespace(pid)}), - oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.IPCNamespace, Path: GetIPCNamespace(pid)}), - oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.UTSNamespace, Path: GetUTSNamespace(pid)}), - } - if namespaces.GetPid() != runtime.NamespaceMode_CONTAINER { - opts = append(opts, oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.PIDNamespace, Path: GetPIDNamespace(pid)})) - } - return oci.Compose(opts...) -} - -// WithDefaultSandboxShares sets the default sandbox CPU shares -func WithDefaultSandboxShares(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Linux == nil { - s.Linux = &runtimespec.Linux{} - } - if s.Linux.Resources == nil { - s.Linux.Resources = &runtimespec.LinuxResources{} - } - if s.Linux.Resources.CPU == nil { - s.Linux.Resources.CPU = &runtimespec.LinuxCPU{} - } - i := uint64(DefaultSandboxCPUshares) - s.Linux.Resources.CPU.Shares = &i - return nil -} - -// WithoutNamespace removes the provided namespace -func WithoutNamespace(t runtimespec.LinuxNamespaceType) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Linux == nil { - return nil - } - var namespaces []runtimespec.LinuxNamespace - for i, ns := range s.Linux.Namespaces { - if ns.Type != t { - namespaces = append(namespaces, s.Linux.Namespaces[i]) - } - } - s.Linux.Namespaces = namespaces - return nil - } -} - -func nullOpt(_ context.Context, _ oci.Client, _ *containers.Container, _ *runtimespec.Spec) error { - return nil -} - -func getCurrentOOMScoreAdj() (int, error) { - b, err := ioutil.ReadFile("/proc/self/oom_score_adj") - if err != nil { - return 0, errors.Wrap(err, "could not get the daemon oom_score_adj") - } - s := strings.TrimSpace(string(b)) - i, err := strconv.Atoi(s) - if err != nil { - return 0, errors.Wrap(err, "could not get the daemon oom_score_adj") - } - return i, nil -} - -func restrictOOMScoreAdj(preferredOOMScoreAdj int) (int, error) { - currentOOMScoreAdj, err := getCurrentOOMScoreAdj() - if err != nil { - return preferredOOMScoreAdj, err - } - if preferredOOMScoreAdj < currentOOMScoreAdj { - return currentOOMScoreAdj, nil - } - return preferredOOMScoreAdj, nil -} - -const ( - // netNSFormat is the format of network namespace of a process. - netNSFormat = "/proc/%v/ns/net" - // ipcNSFormat is the format of ipc namespace of a process. - ipcNSFormat = "/proc/%v/ns/ipc" - // utsNSFormat is the format of uts namespace of a process. - utsNSFormat = "/proc/%v/ns/uts" - // pidNSFormat is the format of pid namespace of a process. - pidNSFormat = "/proc/%v/ns/pid" -) - -// GetNetworkNamespace returns the network namespace of a process. -func GetNetworkNamespace(pid uint32) string { - return fmt.Sprintf(netNSFormat, pid) -} - -// GetIPCNamespace returns the ipc namespace of a process. -func GetIPCNamespace(pid uint32) string { - return fmt.Sprintf(ipcNSFormat, pid) -} - -// GetUTSNamespace returns the uts namespace of a process. -func GetUTSNamespace(pid uint32) string { - return fmt.Sprintf(utsNSFormat, pid) -} - -// GetPIDNamespace returns the pid namespace of a process. -func GetPIDNamespace(pid uint32) string { - return fmt.Sprintf(pidNSFormat, pid) -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/opts/spec_windows.go b/vendor/github.com/containerd/cri/pkg/containerd/opts/spec_windows.go deleted file mode 100644 index 50ee19d48..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/opts/spec_windows.go +++ /dev/null @@ -1,224 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package opts - -import ( - "context" - "path/filepath" - "sort" - "strings" - - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - osinterface "github.com/containerd/cri/pkg/os" -) - -// WithWindowsNetworkNamespace sets windows network namespace for container. -// TODO(windows): Move this into container/containerd. -func WithWindowsNetworkNamespace(path string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Windows == nil { - s.Windows = &runtimespec.Windows{} - } - if s.Windows.Network == nil { - s.Windows.Network = &runtimespec.WindowsNetwork{} - } - s.Windows.Network.NetworkNamespace = path - return nil - } -} - -// namedPipePath returns true if the given path is to a named pipe. -func namedPipePath(p string) bool { - return strings.HasPrefix(p, `\\.\pipe\`) -} - -// cleanMount returns a cleaned version of the mount path. The input is returned -// as-is if it is a named pipe path. -func cleanMount(p string) string { - if namedPipePath(p) { - return p - } - return filepath.Clean(p) -} - -// WithWindowsMounts sorts and adds runtime and CRI mounts to the spec for -// windows container. -func WithWindowsMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*runtime.Mount) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, _ *containers.Container, s *runtimespec.Spec) error { - // mergeMounts merge CRI mounts with extra mounts. If a mount destination - // is mounted by both a CRI mount and an extra mount, the CRI mount will - // be kept. - var ( - criMounts = config.GetMounts() - mounts = append([]*runtime.Mount{}, criMounts...) - ) - // Copy all mounts from extra mounts, except for mounts overridden by CRI. - for _, e := range extra { - found := false - for _, c := range criMounts { - if cleanMount(e.ContainerPath) == cleanMount(c.ContainerPath) { - found = true - break - } - } - if !found { - mounts = append(mounts, e) - } - } - - // Sort mounts in number of parts. This ensures that high level mounts don't - // shadow other mounts. - sort.Sort(orderedMounts(mounts)) - - // Copy all mounts from default mounts, except for - // mounts overridden by supplied mount; - mountSet := make(map[string]struct{}) - for _, m := range mounts { - mountSet[cleanMount(m.ContainerPath)] = struct{}{} - } - - defaultMounts := s.Mounts - s.Mounts = nil - - for _, m := range defaultMounts { - dst := cleanMount(m.Destination) - if _, ok := mountSet[dst]; ok { - // filter out mount overridden by a supplied mount - continue - } - s.Mounts = append(s.Mounts, m) - } - - for _, mount := range mounts { - var ( - dst = mount.GetContainerPath() - src = mount.GetHostPath() - ) - // In the case of a named pipe mount on Windows, don't stat the file - // or do other operations that open it, as that could interfere with - // the listening process. filepath.Clean also breaks named pipe - // paths, so don't use it. - if !namedPipePath(src) { - if _, err := osi.Stat(src); err != nil { - // If the source doesn't exist, return an error instead - // of creating the source. This aligns with Docker's - // behavior on windows. - return errors.Wrapf(err, "failed to stat %q", src) - } - var err error - src, err = osi.ResolveSymbolicLink(src) - if err != nil { - return errors.Wrapf(err, "failed to resolve symlink %q", src) - } - // hcsshim requires clean path, especially '/' -> '\'. - src = filepath.Clean(src) - dst = filepath.Clean(dst) - } - - var options []string - // NOTE(random-liu): we don't change all mounts to `ro` when root filesystem - // is readonly. This is different from docker's behavior, but make more sense. - if mount.GetReadonly() { - options = append(options, "ro") - } else { - options = append(options, "rw") - } - s.Mounts = append(s.Mounts, runtimespec.Mount{ - Source: src, - Destination: dst, - Options: options, - }) - } - return nil - } -} - -// WithWindowsResources sets the provided resource restrictions for windows. -func WithWindowsResources(resources *runtime.WindowsContainerResources) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if resources == nil { - return nil - } - if s.Windows == nil { - s.Windows = &runtimespec.Windows{} - } - if s.Windows.Resources == nil { - s.Windows.Resources = &runtimespec.WindowsResources{} - } - if s.Windows.Resources.CPU == nil { - s.Windows.Resources.CPU = &runtimespec.WindowsCPUResources{} - } - if s.Windows.Resources.Memory == nil { - s.Windows.Resources.Memory = &runtimespec.WindowsMemoryResources{} - } - - var ( - count = uint64(resources.GetCpuCount()) - shares = uint16(resources.GetCpuShares()) - max = uint16(resources.GetCpuMaximum()) - limit = uint64(resources.GetMemoryLimitInBytes()) - ) - if count != 0 { - s.Windows.Resources.CPU.Count = &count - } - if shares != 0 { - s.Windows.Resources.CPU.Shares = &shares - } - if max != 0 { - s.Windows.Resources.CPU.Maximum = &max - } - if limit != 0 { - s.Windows.Resources.Memory.Limit = &limit - } - return nil - } -} - -// WithWindowsDefaultSandboxShares sets the default sandbox CPU shares -func WithWindowsDefaultSandboxShares(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Windows == nil { - s.Windows = &runtimespec.Windows{} - } - if s.Windows.Resources == nil { - s.Windows.Resources = &runtimespec.WindowsResources{} - } - if s.Windows.Resources.CPU == nil { - s.Windows.Resources.CPU = &runtimespec.WindowsCPUResources{} - } - i := uint16(DefaultSandboxCPUshares) - s.Windows.Resources.CPU.Shares = &i - return nil -} - -// WithWindowsCredentialSpec assigns `credentialSpec` to the -// `runtime.Spec.Windows.CredentialSpec` field. -func WithWindowsCredentialSpec(credentialSpec string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { - if s.Windows == nil { - s.Windows = &runtimespec.Windows{} - } - s.Windows.CredentialSpec = credentialSpec - return nil - } -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/opts/task.go b/vendor/github.com/containerd/cri/pkg/containerd/opts/task.go deleted file mode 100644 index 622e3e9ce..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/opts/task.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package opts - -import ( - "context" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/runtime/linux/runctypes" -) - -// WithContainerdShimCgroup returns function that sets the containerd -// shim cgroup path -func WithContainerdShimCgroup(path string) containerd.NewTaskOpts { - return func(_ context.Context, _ *containerd.Client, r *containerd.TaskInfo) error { - r.Options = &runctypes.CreateOptions{ - ShimCgroup: path, - } - return nil - } -} - -//TODO: Since Options is an interface different WithXXX will be needed to set different -// combinations of CreateOptions. diff --git a/vendor/github.com/containerd/cri/pkg/containerd/platforms/default_unix.go b/vendor/github.com/containerd/cri/pkg/containerd/platforms/default_unix.go deleted file mode 100644 index ca7de553c..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/platforms/default_unix.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package platforms - -import ( - "github.com/containerd/containerd/platforms" -) - -// Default returns the current platform's default platform specification. -func Default() platforms.MatchComparer { - return platforms.Default() -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/platforms/default_windows.go b/vendor/github.com/containerd/cri/pkg/containerd/platforms/default_windows.go deleted file mode 100644 index f8679f21f..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/platforms/default_windows.go +++ /dev/null @@ -1,77 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package platforms - -import ( - "fmt" - "strconv" - "strings" - - "github.com/containerd/containerd/platforms" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - "golang.org/x/sys/windows" -) - -type matchComparer struct { - defaults platforms.Matcher - osVersionPrefix string -} - -// Match matches platform with the same windows major, minor -// and build version. -func (m matchComparer) Match(p imagespec.Platform) bool { - if m.defaults.Match(p) { - // TODO(windows): Figure out whether OSVersion is deprecated. - return strings.HasPrefix(p.OSVersion, m.osVersionPrefix) - } - return false -} - -// Less sorts matched platforms in front of other platforms. -// For matched platforms, it puts platforms with larger revision -// number in front. -func (m matchComparer) Less(p1, p2 imagespec.Platform) bool { - m1, m2 := m.Match(p1), m.Match(p2) - if m1 && m2 { - r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion) - return r1 > r2 - } - return m1 && !m2 -} - -func revision(v string) int { - parts := strings.Split(v, ".") - if len(parts) < 4 { - return 0 - } - r, err := strconv.Atoi(parts[3]) - if err != nil { - return 0 - } - return r -} - -// Default returns the current platform's default platform specification. -func Default() platforms.MatchComparer { - major, minor, build := windows.RtlGetNtVersionNumbers() - return matchComparer{ - defaults: platforms.Only(platforms.DefaultSpec()), - osVersionPrefix: fmt.Sprintf("%d.%d.%d", major, minor, build), - } -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/util/util.go b/vendor/github.com/containerd/cri/pkg/containerd/util/util.go deleted file mode 100644 index ec062df0d..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/util/util.go +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package util - -import ( - "time" - - "github.com/containerd/containerd/namespaces" - "golang.org/x/net/context" - - "github.com/containerd/cri/pkg/constants" -) - -// deferCleanupTimeout is the default timeout for containerd cleanup operations -// in defer. -const deferCleanupTimeout = 1 * time.Minute - -// DeferContext returns a context for containerd cleanup operations in defer. -// A default timeout is applied to avoid cleanup operation pending forever. -func DeferContext() (context.Context, context.CancelFunc) { - return context.WithTimeout(NamespacedContext(), deferCleanupTimeout) -} - -// NamespacedContext returns a context with kubernetes namespace set. -func NamespacedContext() context.Context { - return WithNamespace(context.Background()) -} - -// WithNamespace adds kubernetes namespace to the context. -func WithNamespace(ctx context.Context) context.Context { - return namespaces.WithNamespace(ctx, constants.K8sContainerdNamespace) -} diff --git a/vendor/github.com/containerd/cri/pkg/ioutil/read_closer.go b/vendor/github.com/containerd/cri/pkg/ioutil/read_closer.go deleted file mode 100644 index fbc30a6f7..000000000 --- a/vendor/github.com/containerd/cri/pkg/ioutil/read_closer.go +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package ioutil - -import "io" - -// writeCloseInformer wraps a reader with a close function. -type wrapReadCloser struct { - reader *io.PipeReader - writer *io.PipeWriter -} - -// NewWrapReadCloser creates a wrapReadCloser from a reader. -// NOTE(random-liu): To avoid goroutine leakage, the reader passed in -// must be eventually closed by the caller. -func NewWrapReadCloser(r io.Reader) io.ReadCloser { - pr, pw := io.Pipe() - go func() { - _, _ = io.Copy(pw, r) - pr.Close() - pw.Close() - }() - return &wrapReadCloser{ - reader: pr, - writer: pw, - } -} - -// Read reads up to len(p) bytes into p. -func (w *wrapReadCloser) Read(p []byte) (int, error) { - n, err := w.reader.Read(p) - if err == io.ErrClosedPipe { - return n, io.EOF - } - return n, err -} - -// Close closes read closer. -func (w *wrapReadCloser) Close() error { - w.reader.Close() - w.writer.Close() - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/ioutil/write_closer.go b/vendor/github.com/containerd/cri/pkg/ioutil/write_closer.go deleted file mode 100644 index c816c514a..000000000 --- a/vendor/github.com/containerd/cri/pkg/ioutil/write_closer.go +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package ioutil - -import ( - "io" - "sync" -) - -// writeCloseInformer wraps passed in write closer with a close channel. -// Caller could wait on the close channel for the write closer to be -// closed. -type writeCloseInformer struct { - close chan struct{} - wc io.WriteCloser -} - -// NewWriteCloseInformer creates the writeCloseInformer from a write closer. -func NewWriteCloseInformer(wc io.WriteCloser) (io.WriteCloser, <-chan struct{}) { - close := make(chan struct{}) - return &writeCloseInformer{ - close: close, - wc: wc, - }, close -} - -// Write passes through the data into the internal write closer. -func (w *writeCloseInformer) Write(p []byte) (int, error) { - return w.wc.Write(p) -} - -// Close closes the internal write closer and inform the close channel. -func (w *writeCloseInformer) Close() error { - err := w.wc.Close() - close(w.close) - return err -} - -// nopWriteCloser wraps passed in writer with a nop close function. -type nopWriteCloser struct { - w io.Writer -} - -// NewNopWriteCloser creates the nopWriteCloser from a writer. -func NewNopWriteCloser(w io.Writer) io.WriteCloser { - return &nopWriteCloser{w: w} -} - -// Write passes through the data into the internal writer. -func (n *nopWriteCloser) Write(p []byte) (int, error) { - return n.w.Write(p) -} - -// Close is a nop close function. -func (n *nopWriteCloser) Close() error { - return nil -} - -// serialWriteCloser wraps a write closer and makes sure all writes -// are done in serial. -// Parallel write won't intersect with each other. Use case: -// 1) Pipe: Write content longer than PIPE_BUF. -// See http://man7.org/linux/man-pages/man7/pipe.7.html -// 2) <3.14 Linux Kernel: write is not atomic -// See http://man7.org/linux/man-pages/man2/write.2.html -type serialWriteCloser struct { - mu sync.Mutex - wc io.WriteCloser -} - -// NewSerialWriteCloser creates a SerialWriteCloser from a write closer. -func NewSerialWriteCloser(wc io.WriteCloser) io.WriteCloser { - return &serialWriteCloser{wc: wc} -} - -// Write writes a group of byte arrays in order atomically. -func (s *serialWriteCloser) Write(data []byte) (int, error) { - s.mu.Lock() - defer s.mu.Unlock() - return s.wc.Write(data) -} - -// Close closes the write closer. -func (s *serialWriteCloser) Close() error { - s.mu.Lock() - defer s.mu.Unlock() - return s.wc.Close() -} diff --git a/vendor/github.com/containerd/cri/pkg/ioutil/writer_group.go b/vendor/github.com/containerd/cri/pkg/ioutil/writer_group.go deleted file mode 100644 index 0ed550497..000000000 --- a/vendor/github.com/containerd/cri/pkg/ioutil/writer_group.go +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package ioutil - -import ( - "errors" - "io" - "sync" -) - -// WriterGroup is a group of writers. Writer could be dynamically -// added and removed. -type WriterGroup struct { - mu sync.Mutex - writers map[string]io.WriteCloser - closed bool -} - -var _ io.Writer = &WriterGroup{} - -// NewWriterGroup creates an empty writer group. -func NewWriterGroup() *WriterGroup { - return &WriterGroup{ - writers: make(map[string]io.WriteCloser), - } -} - -// Add adds a writer into the group. The writer will be closed -// if the writer group is closed. -func (g *WriterGroup) Add(key string, w io.WriteCloser) { - g.mu.Lock() - defer g.mu.Unlock() - if g.closed { - w.Close() - return - } - g.writers[key] = w -} - -// Get gets a writer from the group, returns nil if the writer -// doesn't exist. -func (g *WriterGroup) Get(key string) io.WriteCloser { - g.mu.Lock() - defer g.mu.Unlock() - return g.writers[key] -} - -// Remove removes a writer from the group. -func (g *WriterGroup) Remove(key string) { - g.mu.Lock() - defer g.mu.Unlock() - w, ok := g.writers[key] - if !ok { - return - } - w.Close() - delete(g.writers, key) -} - -// Write writes data into each writer. If a writer returns error, -// it will be closed and removed from the writer group. It returns -// error if writer group is empty. -func (g *WriterGroup) Write(p []byte) (int, error) { - g.mu.Lock() - defer g.mu.Unlock() - for k, w := range g.writers { - n, err := w.Write(p) - if err == nil && len(p) == n { - continue - } - // The writer is closed or in bad state, remove it. - w.Close() - delete(g.writers, k) - } - if len(g.writers) == 0 { - return 0, errors.New("writer group is empty") - } - return len(p), nil -} - -// Close closes the writer group. Write will return error after -// closed. -func (g *WriterGroup) Close() { - g.mu.Lock() - defer g.mu.Unlock() - for _, w := range g.writers { - w.Close() - } - g.writers = nil - g.closed = true -} diff --git a/vendor/github.com/containerd/cri/pkg/netns/netns_unix.go b/vendor/github.com/containerd/cri/pkg/netns/netns_unix.go deleted file mode 100644 index 7449e2350..000000000 --- a/vendor/github.com/containerd/cri/pkg/netns/netns_unix.go +++ /dev/null @@ -1,222 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -// Copyright 2018 CNI 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 netns - -import ( - "crypto/rand" - "fmt" - "os" - "path" - "runtime" - "sync" - - cnins "github.com/containernetworking/plugins/pkg/ns" - "github.com/docker/docker/pkg/symlink" - "github.com/pkg/errors" - "golang.org/x/sys/unix" - - osinterface "github.com/containerd/cri/pkg/os" -) - -const nsRunDir = "/var/run/netns" - -// Some of the following functions are migrated from -// https://github.com/containernetworking/plugins/blob/master/pkg/testutils/netns_linux.go - -// newNS creates a new persistent (bind-mounted) network namespace and returns the -// path to the network namespace. -func newNS() (nsPath string, err error) { - b := make([]byte, 16) - if _, err := rand.Reader.Read(b); err != nil { - return "", errors.Wrap(err, "failed to generate random netns name") - } - - // Create the directory for mounting network namespaces - // This needs to be a shared mountpoint in case it is mounted in to - // other namespaces (containers) - if err := os.MkdirAll(nsRunDir, 0755); err != nil { - return "", err - } - - // create an empty file at the mount point - nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) - nsPath = path.Join(nsRunDir, nsName) - mountPointFd, err := os.Create(nsPath) - if err != nil { - return "", err - } - mountPointFd.Close() - - defer func() { - // Ensure the mount point is cleaned up on errors - if err != nil { - os.RemoveAll(nsPath) // nolint: errcheck - } - }() - - var wg sync.WaitGroup - wg.Add(1) - - // do namespace work in a dedicated goroutine, so that we can safely - // Lock/Unlock OSThread without upsetting the lock/unlock state of - // the caller of this function - go (func() { - defer wg.Done() - runtime.LockOSThread() - // Don't unlock. By not unlocking, golang will kill the OS thread when the - // goroutine is done (for go1.10+) - - var origNS cnins.NetNS - origNS, err = cnins.GetNS(getCurrentThreadNetNSPath()) - if err != nil { - return - } - defer origNS.Close() - - // create a new netns on the current thread - err = unix.Unshare(unix.CLONE_NEWNET) - if err != nil { - return - } - - // Put this thread back to the orig ns, since it might get reused (pre go1.10) - defer origNS.Set() // nolint: errcheck - - // bind mount the netns from the current thread (from /proc) onto the - // mount point. This causes the namespace to persist, even when there - // are no threads in the ns. - err = unix.Mount(getCurrentThreadNetNSPath(), nsPath, "none", unix.MS_BIND, "") - if err != nil { - err = errors.Wrapf(err, "failed to bind mount ns at %s", nsPath) - } - })() - wg.Wait() - - if err != nil { - return "", errors.Wrap(err, "failed to create namespace") - } - - return nsPath, nil -} - -// unmountNS unmounts the NS held by the netns object. unmountNS is idempotent. -func unmountNS(path string) error { - if _, err := os.Stat(path); err != nil { - if os.IsNotExist(err) { - return nil - } - return errors.Wrap(err, "failed to stat netns") - } - path, err := symlink.FollowSymlinkInScope(path, "/") - if err != nil { - return errors.Wrap(err, "failed to follow symlink") - } - if err := osinterface.Unmount(path); err != nil && !os.IsNotExist(err) { - return errors.Wrap(err, "failed to umount netns") - } - if err := os.RemoveAll(path); err != nil { - return errors.Wrap(err, "failed to remove netns") - } - return nil -} - -// getCurrentThreadNetNSPath copied from pkg/ns -func getCurrentThreadNetNSPath() string { - // /proc/self/ns/net returns the namespace of the main thread, not - // of whatever thread this goroutine is running on. Make sure we - // use the thread's net namespace since the thread is switching around - return fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid()) -} - -// NetNS holds network namespace. -type NetNS struct { - path string -} - -// NewNetNS creates a network namespace. -func NewNetNS() (*NetNS, error) { - path, err := newNS() - if err != nil { - return nil, errors.Wrap(err, "failed to setup netns") - } - return &NetNS{path: path}, nil -} - -// LoadNetNS loads existing network namespace. -func LoadNetNS(path string) *NetNS { - return &NetNS{path: path} -} - -// Remove removes network namepace. Remove is idempotent, meaning it might -// be invoked multiple times and provides consistent result. -func (n *NetNS) Remove() error { - return unmountNS(n.path) -} - -// Closed checks whether the network namespace has been closed. -func (n *NetNS) Closed() (bool, error) { - ns, err := cnins.GetNS(n.path) - if err != nil { - if _, ok := err.(cnins.NSPathNotExistErr); ok { - // The network namespace has already been removed. - return true, nil - } - if _, ok := err.(cnins.NSPathNotNSErr); ok { - // The network namespace is not mounted, remove it. - if err := os.RemoveAll(n.path); err != nil { - return false, errors.Wrap(err, "remove netns") - } - return true, nil - } - return false, errors.Wrap(err, "get netns fd") - } - if err := ns.Close(); err != nil { - return false, errors.Wrap(err, "close netns fd") - } - return false, nil -} - -// GetPath returns network namespace path for sandbox container -func (n *NetNS) GetPath() string { - return n.path -} - -// Do runs a function in the network namespace. -func (n *NetNS) Do(f func(cnins.NetNS) error) error { - ns, err := cnins.GetNS(n.path) - if err != nil { - return errors.Wrap(err, "get netns fd") - } - defer ns.Close() // nolint: errcheck - return ns.Do(f) -} diff --git a/vendor/github.com/containerd/cri/pkg/netns/netns_windows.go b/vendor/github.com/containerd/cri/pkg/netns/netns_windows.go deleted file mode 100644 index 62dac4151..000000000 --- a/vendor/github.com/containerd/cri/pkg/netns/netns_windows.go +++ /dev/null @@ -1,78 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package netns - -import "github.com/Microsoft/hcsshim/hcn" - -// NetNS holds network namespace for sandbox -type NetNS struct { - path string -} - -// NewNetNS creates a network namespace for the sandbox -func NewNetNS() (*NetNS, error) { - temp := hcn.HostComputeNamespace{} - hcnNamespace, err := temp.Create() - if err != nil { - return nil, err - } - - return &NetNS{path: hcnNamespace.Id}, nil -} - -// LoadNetNS loads existing network namespace. -func LoadNetNS(path string) *NetNS { - return &NetNS{path: path} -} - -// Remove removes network namepace if it exists and not closed. Remove is idempotent, -// meaning it might be invoked multiple times and provides consistent result. -func (n *NetNS) Remove() error { - hcnNamespace, err := hcn.GetNamespaceByID(n.path) - if err != nil { - if hcn.IsNotFoundError(err) { - return nil - } - return err - } - err = hcnNamespace.Delete() - if err == nil || hcn.IsNotFoundError(err) { - return nil - } - return err -} - -// Closed checks whether the network namespace has been closed. -func (n *NetNS) Closed() (bool, error) { - _, err := hcn.GetNamespaceByID(n.path) - if err == nil { - return false, nil - } - if hcn.IsNotFoundError(err) { - return true, nil - } - return false, err -} - -// GetPath returns network namespace path for sandbox container -func (n *NetNS) GetPath() string { - return n.path -} - -// NOTE: Do function is not supported. diff --git a/vendor/github.com/containerd/cri/pkg/os/os.go b/vendor/github.com/containerd/cri/pkg/os/os.go deleted file mode 100644 index 807a34d92..000000000 --- a/vendor/github.com/containerd/cri/pkg/os/os.go +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package os - -import ( - "io" - "io/ioutil" - "os" - "path/filepath" - - "github.com/docker/docker/pkg/symlink" -) - -// OS collects system level operations that need to be mocked out -// during tests. -type OS interface { - MkdirAll(path string, perm os.FileMode) error - RemoveAll(path string) error - Stat(name string) (os.FileInfo, error) - ResolveSymbolicLink(name string) (string, error) - FollowSymlinkInScope(path, scope string) (string, error) - CopyFile(src, dest string, perm os.FileMode) error - WriteFile(filename string, data []byte, perm os.FileMode) error - Hostname() (string, error) -} - -// RealOS is used to dispatch the real system level operations. -type RealOS struct{} - -// MkdirAll will call os.MkdirAll to create a directory. -func (RealOS) MkdirAll(path string, perm os.FileMode) error { - return os.MkdirAll(path, perm) -} - -// RemoveAll will call os.RemoveAll to remove the path and its children. -func (RealOS) RemoveAll(path string) error { - return os.RemoveAll(path) -} - -// Stat will call os.Stat to get the status of the given file. -func (RealOS) Stat(name string) (os.FileInfo, error) { - return os.Stat(name) -} - -// ResolveSymbolicLink will follow any symbolic links -func (RealOS) ResolveSymbolicLink(path string) (string, error) { - info, err := os.Lstat(path) - if err != nil { - return "", err - } - if info.Mode()&os.ModeSymlink != os.ModeSymlink { - return path, nil - } - return filepath.EvalSymlinks(path) -} - -// FollowSymlinkInScope will call symlink.FollowSymlinkInScope. -func (RealOS) FollowSymlinkInScope(path, scope string) (string, error) { - return symlink.FollowSymlinkInScope(path, scope) -} - -// CopyFile will copy src file to dest file -func (RealOS) CopyFile(src, dest string, perm os.FileMode) error { - in, err := os.Open(src) - if err != nil { - return err - } - defer in.Close() - - out, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) - if err != nil { - return err - } - defer out.Close() - - _, err = io.Copy(out, in) - return err -} - -// WriteFile will call ioutil.WriteFile to write data into a file. -func (RealOS) WriteFile(filename string, data []byte, perm os.FileMode) error { - return ioutil.WriteFile(filename, data, perm) -} - -// Hostname will call os.Hostname to get the hostname of the host. -func (RealOS) Hostname() (string, error) { - return os.Hostname() -} diff --git a/vendor/github.com/containerd/cri/pkg/os/os_unix.go b/vendor/github.com/containerd/cri/pkg/os/os_unix.go deleted file mode 100644 index 51f57871d..000000000 --- a/vendor/github.com/containerd/cri/pkg/os/os_unix.go +++ /dev/null @@ -1,59 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package os - -import ( - "github.com/containerd/containerd/mount" - "golang.org/x/sys/unix" -) - -// UNIX collects unix system level operations that need to be -// mocked out during tests. -type UNIX interface { - Mount(source string, target string, fstype string, flags uintptr, data string) error - Unmount(target string) error - LookupMount(path string) (mount.Info, error) -} - -// Mount will call unix.Mount to mount the file. -func (RealOS) Mount(source string, target string, fstype string, flags uintptr, data string) error { - return unix.Mount(source, target, fstype, flags, data) -} - -// Unmount will call Unmount to unmount the file. -func (RealOS) Unmount(target string) error { - return Unmount(target) -} - -// LookupMount gets mount info of a given path. -func (RealOS) LookupMount(path string) (mount.Info, error) { - return mount.Lookup(path) -} - -// Unmount unmounts the target. It does not return an error in case the target is not mounted. -// In case the target does not exist, the appropriate error is returned. -func Unmount(target string) error { - err := unix.Unmount(target, unix.MNT_DETACH) - if err == unix.EINVAL { - // ignore "not mounted" error - err = nil - } - - return err -} diff --git a/vendor/github.com/containerd/cri/pkg/registrar/registrar.go b/vendor/github.com/containerd/cri/pkg/registrar/registrar.go deleted file mode 100644 index b83e7ce85..000000000 --- a/vendor/github.com/containerd/cri/pkg/registrar/registrar.go +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package registrar - -import ( - "sync" - - "github.com/pkg/errors" -) - -// Registrar stores one-to-one name<->key mappings. -// Names and keys must be unique. -// Registrar is safe for concurrent access. -type Registrar struct { - lock sync.Mutex - nameToKey map[string]string - keyToName map[string]string -} - -// NewRegistrar creates a new Registrar with the empty indexes. -func NewRegistrar() *Registrar { - return &Registrar{ - nameToKey: make(map[string]string), - keyToName: make(map[string]string), - } -} - -// Reserve registers a name<->key mapping, name or key must not -// be empty. -// Reserve is idempotent. -// Attempting to reserve a conflict key<->name mapping results -// in an error. -// A name<->key reservation is globally unique. -func (r *Registrar) Reserve(name, key string) error { - r.lock.Lock() - defer r.lock.Unlock() - - if name == "" || key == "" { - return errors.Errorf("invalid name %q or key %q", name, key) - } - - if k, exists := r.nameToKey[name]; exists { - if k != key { - return errors.Errorf("name %q is reserved for %q", name, k) - } - return nil - } - - if n, exists := r.keyToName[key]; exists { - if n != name { - return errors.Errorf("key %q is reserved for %q", key, n) - } - return nil - } - - r.nameToKey[name] = key - r.keyToName[key] = name - return nil -} - -// ReleaseByName releases the reserved name<->key mapping by name. -// Once released, the name and the key can be reserved again. -func (r *Registrar) ReleaseByName(name string) { - r.lock.Lock() - defer r.lock.Unlock() - - key, exists := r.nameToKey[name] - if !exists { - return - } - - delete(r.nameToKey, name) - delete(r.keyToName, key) -} - -// ReleaseByKey release the reserved name<->key mapping by key. -func (r *Registrar) ReleaseByKey(key string) { - r.lock.Lock() - defer r.lock.Unlock() - - name, exists := r.keyToName[key] - if !exists { - return - } - - delete(r.nameToKey, name) - delete(r.keyToName, key) -} diff --git a/vendor/github.com/containerd/cri/pkg/seccomp/seccomp_linux.go b/vendor/github.com/containerd/cri/pkg/seccomp/seccomp_linux.go deleted file mode 100644 index d41a98bf1..000000000 --- a/vendor/github.com/containerd/cri/pkg/seccomp/seccomp_linux.go +++ /dev/null @@ -1,88 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* - Copyright The runc 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 seccomp - -import ( - "bufio" - "os" - "strings" - - "golang.org/x/sys/unix" -) - -// IsEnabled returns if the kernel has been configured to support seccomp. -// From https://github.com/opencontainers/runc/blob/v1.0.0-rc91/libcontainer/seccomp/seccomp_linux.go#L86-L102 -func IsEnabled() bool { - // Try to read from /proc/self/status for kernels > 3.8 - s, err := parseStatusFile("/proc/self/status") - if err != nil { - // Check if Seccomp is supported, via CONFIG_SECCOMP. - if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL { - // Make sure the kernel has CONFIG_SECCOMP_FILTER. - if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL { - return true - } - } - return false - } - _, ok := s["Seccomp"] - return ok -} - -// parseStatusFile is from https://github.com/opencontainers/runc/blob/v1.0.0-rc91/libcontainer/seccomp/seccomp_linux.go#L243-L268 -func parseStatusFile(path string) (map[string]string, error) { - f, err := os.Open(path) - if err != nil { - return nil, err - } - defer f.Close() - - s := bufio.NewScanner(f) - status := make(map[string]string) - - for s.Scan() { - text := s.Text() - parts := strings.Split(text, ":") - - if len(parts) <= 1 { - continue - } - - status[parts[0]] = parts[1] - } - if err := s.Err(); err != nil { - return nil, err - } - - return status, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/seccomp/seccomp_unsupported.go b/vendor/github.com/containerd/cri/pkg/seccomp/seccomp_unsupported.go deleted file mode 100644 index 3f7562605..000000000 --- a/vendor/github.com/containerd/cri/pkg/seccomp/seccomp_unsupported.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build !linux - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package seccomp - -func IsEnabled() bool { - return false -} diff --git a/vendor/github.com/containerd/cri/pkg/server/bandwidth/doc.go b/vendor/github.com/containerd/cri/pkg/server/bandwidth/doc.go deleted file mode 100644 index 1fd55229d..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/bandwidth/doc.go +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package bandwidth provides utilities for bandwidth shaping -package bandwidth diff --git a/vendor/github.com/containerd/cri/pkg/server/bandwidth/fake_shaper.go b/vendor/github.com/containerd/cri/pkg/server/bandwidth/fake_shaper.go deleted file mode 100644 index e987ceca6..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/bandwidth/fake_shaper.go +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bandwidth - -import ( - "errors" - - "k8s.io/apimachinery/pkg/api/resource" -) - -// FakeShaper provides an implementation of the bandwith.Shaper. -// Beware this is implementation has no features besides Reset and GetCIDRs. -type FakeShaper struct { - CIDRs []string - ResetCIDRs []string -} - -// Limit is not implemented -func (f *FakeShaper) Limit(cidr string, egress, ingress *resource.Quantity) error { - return errors.New("unimplemented") -} - -// Reset appends a particular CIDR to the set of ResetCIDRs being managed by this shaper -func (f *FakeShaper) Reset(cidr string) error { - f.ResetCIDRs = append(f.ResetCIDRs, cidr) - return nil -} - -// ReconcileInterface is not implemented -func (f *FakeShaper) ReconcileInterface() error { - return errors.New("unimplemented") -} - -// ReconcileCIDR is not implemented -func (f *FakeShaper) ReconcileCIDR(cidr string, egress, ingress *resource.Quantity) error { - return errors.New("unimplemented") -} - -// GetCIDRs returns the set of CIDRs that are being managed by this shaper -func (f *FakeShaper) GetCIDRs() ([]string, error) { - return f.CIDRs, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/bandwidth/interfaces.go b/vendor/github.com/containerd/cri/pkg/server/bandwidth/interfaces.go deleted file mode 100644 index 9eb4bfb60..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/bandwidth/interfaces.go +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bandwidth - -import "k8s.io/apimachinery/pkg/api/resource" - -// Shaper is designed so that the shaper structs created -// satisfy the Shaper interface. -type Shaper interface { - // Limit the bandwidth for a particular CIDR on a particular interface - // * ingress and egress are in bits/second - // * cidr is expected to be a valid network CIDR (e.g. '1.2.3.4/32' or '10.20.0.1/16') - // 'egress' bandwidth limit applies to all packets on the interface whose source matches 'cidr' - // 'ingress' bandwidth limit applies to all packets on the interface whose destination matches 'cidr' - // Limits are aggregate limits for the CIDR, not per IP address. CIDRs must be unique, but can be overlapping, traffic - // that matches multiple CIDRs counts against all limits. - Limit(cidr string, egress, ingress *resource.Quantity) error - // Remove a bandwidth limit for a particular CIDR on a particular network interface - Reset(cidr string) error - // Reconcile the interface managed by this shaper with the state on the ground. - ReconcileInterface() error - // Reconcile a CIDR managed by this shaper with the state on the ground - ReconcileCIDR(cidr string, egress, ingress *resource.Quantity) error - // GetCIDRs returns the set of CIDRs that are being managed by this shaper - GetCIDRs() ([]string, error) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/bandwidth/linux.go b/vendor/github.com/containerd/cri/pkg/server/bandwidth/linux.go deleted file mode 100644 index e8d710825..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/bandwidth/linux.go +++ /dev/null @@ -1,361 +0,0 @@ -// +build linux - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bandwidth - -import ( - "bufio" - "bytes" - "encoding/hex" - "fmt" - "net" - "regexp" - "strings" - - "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/utils/exec" - - "k8s.io/klog/v2" -) - -var ( - classShowMatcher = regexp.MustCompile(`class htb (1:\d+)`) - classAndHandleMatcher = regexp.MustCompile(`filter parent 1:.*fh (\d+::\d+).*flowid (\d+:\d+)`) -) - -// tcShaper provides an implementation of the Shaper interface on Linux using the 'tc' tool. -// In general, using this requires that the caller posses the NET_CAP_ADMIN capability, though if you -// do this within an container, it only requires the NS_CAPABLE capability for manipulations to that -// container's network namespace. -// Uses the hierarchical token bucket queuing discipline (htb), this requires Linux 2.4.20 or newer -// or a custom kernel with that queuing discipline backported. -type tcShaper struct { - e exec.Interface - iface string -} - -// NewTCShaper makes a new tcShaper for the given interface -func NewTCShaper(iface string) Shaper { - shaper := &tcShaper{ - e: exec.New(), - iface: iface, - } - return shaper -} - -func (t *tcShaper) execAndLog(cmdStr string, args ...string) error { - klog.V(6).Infof("Running: %s %s", cmdStr, strings.Join(args, " ")) - cmd := t.e.Command(cmdStr, args...) - out, err := cmd.CombinedOutput() - klog.V(6).Infof("Output from tc: %s", string(out)) - return err -} - -func (t *tcShaper) nextClassID() (int, error) { - data, err := t.e.Command("tc", "class", "show", "dev", t.iface).CombinedOutput() - if err != nil { - return -1, err - } - - scanner := bufio.NewScanner(bytes.NewBuffer(data)) - classes := sets.String{} - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - // skip empty lines - if len(line) == 0 { - continue - } - // expected tc line: - // class htb 1:1 root prio 0 rate 1000Kbit ceil 1000Kbit burst 1600b cburst 1600b - matches := classShowMatcher.FindStringSubmatch(line) - if len(matches) != 2 { - return -1, fmt.Errorf("unexpected output from tc: %s (%v)", scanner.Text(), matches) - } - classes.Insert(matches[1]) - } - - // Make sure it doesn't go forever - for nextClass := 1; nextClass < 10000; nextClass++ { - if !classes.Has(fmt.Sprintf("1:%d", nextClass)) { - return nextClass, nil - } - } - // This should really never happen - return -1, fmt.Errorf("exhausted class space, please try again") -} - -// Convert a CIDR from text to a hex representation -// Strips any masked parts of the IP, so 1.2.3.4/16 becomes hex(1.2.0.0)/ffffffff -func hexCIDR(cidr string) (string, error) { - ip, ipnet, err := net.ParseCIDR(cidr) - if err != nil { - return "", err - } - ip = ip.Mask(ipnet.Mask) - hexIP := hex.EncodeToString([]byte(ip)) - hexMask := ipnet.Mask.String() - return hexIP + "/" + hexMask, nil -} - -// Convert a CIDR from hex representation to text, opposite of the above. -func asciiCIDR(cidr string) (string, error) { - parts := strings.Split(cidr, "/") - if len(parts) != 2 { - return "", fmt.Errorf("unexpected CIDR format: %s", cidr) - } - ipData, err := hex.DecodeString(parts[0]) - if err != nil { - return "", err - } - ip := net.IP(ipData) - - maskData, err := hex.DecodeString(parts[1]) - if err != nil { - return "", err - } - mask := net.IPMask(maskData) - size, _ := mask.Size() - - return fmt.Sprintf("%s/%d", ip.String(), size), nil -} - -func (t *tcShaper) findCIDRClass(cidr string) (classAndHandleList [][]string, found bool, err error) { - data, err := t.e.Command("tc", "filter", "show", "dev", t.iface).CombinedOutput() - if err != nil { - return classAndHandleList, false, err - } - - hex, err := hexCIDR(cidr) - if err != nil { - return classAndHandleList, false, err - } - spec := fmt.Sprintf("match %s", hex) - - scanner := bufio.NewScanner(bytes.NewBuffer(data)) - filter := "" - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if len(line) == 0 { - continue - } - if strings.HasPrefix(line, "filter") { - filter = line - continue - } - if strings.Contains(line, spec) { - // expected tc line: - // `filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1` (old version) or - // `filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw` (new version) - matches := classAndHandleMatcher.FindStringSubmatch(filter) - if len(matches) != 3 { - return classAndHandleList, false, fmt.Errorf("unexpected output from tc: %s %d (%v)", filter, len(matches), matches) - } - resultTmp := []string{matches[2], matches[1]} - classAndHandleList = append(classAndHandleList, resultTmp) - } - } - if len(classAndHandleList) > 0 { - return classAndHandleList, true, nil - } - return classAndHandleList, false, nil -} - -func makeKBitString(rsrc *resource.Quantity) string { - return fmt.Sprintf("%dkbit", (rsrc.Value() / 1000)) -} - -func (t *tcShaper) makeNewClass(rate string) (int, error) { - class, err := t.nextClassID() - if err != nil { - return -1, err - } - if err := t.execAndLog("tc", "class", "add", - "dev", t.iface, - "parent", "1:", - "classid", fmt.Sprintf("1:%d", class), - "htb", "rate", rate); err != nil { - return -1, err - } - return class, nil -} - -func (t *tcShaper) Limit(cidr string, upload, download *resource.Quantity) (err error) { - var downloadClass, uploadClass int - if download != nil { - if downloadClass, err = t.makeNewClass(makeKBitString(download)); err != nil { - return err - } - if err := t.execAndLog("tc", "filter", "add", - "dev", t.iface, - "protocol", "ip", - "parent", "1:0", - "prio", "1", "u32", - "match", "ip", "dst", cidr, - "flowid", fmt.Sprintf("1:%d", downloadClass)); err != nil { - return err - } - } - if upload != nil { - if uploadClass, err = t.makeNewClass(makeKBitString(upload)); err != nil { - return err - } - if err := t.execAndLog("tc", "filter", "add", - "dev", t.iface, - "protocol", "ip", - "parent", "1:0", - "prio", "1", "u32", - "match", "ip", "src", cidr, - "flowid", fmt.Sprintf("1:%d", uploadClass)); err != nil { - return err - } - } - return nil -} - -// tests to see if an interface exists, if it does, return true and the status line for the interface -// returns false, "", if an error occurs. -func (t *tcShaper) interfaceExists() (bool, string, error) { - data, err := t.e.Command("tc", "qdisc", "show", "dev", t.iface).CombinedOutput() - if err != nil { - return false, "", err - } - value := strings.TrimSpace(string(data)) - if len(value) == 0 { - return false, "", nil - } - // Newer versions of tc and/or the kernel return the following instead of nothing: - // qdisc noqueue 0: root refcnt 2 - fields := strings.Fields(value) - if len(fields) > 1 && fields[1] == "noqueue" { - return false, "", nil - } - return true, value, nil -} - -func (t *tcShaper) ReconcileCIDR(cidr string, upload, download *resource.Quantity) error { - _, found, err := t.findCIDRClass(cidr) - if err != nil { - return err - } - if !found { - return t.Limit(cidr, upload, download) - } - // TODO: actually check bandwidth limits here - return nil -} - -func (t *tcShaper) ReconcileInterface() error { - exists, output, err := t.interfaceExists() - if err != nil { - return err - } - if !exists { - klog.V(4).Info("Didn't find bandwidth interface, creating") - return t.initializeInterface() - } - fields := strings.Split(output, " ") - if len(fields) < 12 || fields[1] != "htb" || fields[2] != "1:" { - if err := t.deleteInterface(fields[2]); err != nil { - return err - } - return t.initializeInterface() - } - return nil -} - -func (t *tcShaper) initializeInterface() error { - return t.execAndLog("tc", "qdisc", "add", "dev", t.iface, "root", "handle", "1:", "htb", "default", "30") -} - -func (t *tcShaper) Reset(cidr string) error { - classAndHandle, found, err := t.findCIDRClass(cidr) - if err != nil { - return err - } - if !found { - return fmt.Errorf("Failed to find cidr: %s on interface: %s", cidr, t.iface) - } - for i := 0; i < len(classAndHandle); i++ { - if err := t.execAndLog("tc", "filter", "del", - "dev", t.iface, - "parent", "1:", - "proto", "ip", - "prio", "1", - "handle", classAndHandle[i][1], "u32"); err != nil { - return err - } - if err := t.execAndLog("tc", "class", "del", - "dev", t.iface, - "parent", "1:", - "classid", classAndHandle[i][0]); err != nil { - return err - } - } - return nil -} - -func (t *tcShaper) deleteInterface(class string) error { - return t.execAndLog("tc", "qdisc", "delete", "dev", t.iface, "root", "handle", class) -} - -func (t *tcShaper) GetCIDRs() ([]string, error) { - data, err := t.e.Command("tc", "filter", "show", "dev", t.iface).CombinedOutput() - if err != nil { - return nil, err - } - - result := []string{} - scanner := bufio.NewScanner(bytes.NewBuffer(data)) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if len(line) == 0 { - continue - } - if strings.Contains(line, "match") { - parts := strings.Split(line, " ") - // expected tc line: - // match at - if len(parts) != 4 { - return nil, fmt.Errorf("unexpected output: %v", parts) - } - cidr, err := asciiCIDR(parts[1]) - if err != nil { - return nil, err - } - result = append(result, cidr) - } - } - return result, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/bandwidth/unsupported.go b/vendor/github.com/containerd/cri/pkg/server/bandwidth/unsupported.go deleted file mode 100644 index 12c5ad83b..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/bandwidth/unsupported.go +++ /dev/null @@ -1,69 +0,0 @@ -// +build !linux - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bandwidth - -import ( - "errors" - - "k8s.io/apimachinery/pkg/api/resource" -) - -type unsupportedShaper struct { -} - -// NewTCShaper makes a new unsupportedShapper for the given interface -func NewTCShaper(iface string) Shaper { - return &unsupportedShaper{} -} - -func (f *unsupportedShaper) Limit(cidr string, egress, ingress *resource.Quantity) error { - return errors.New("unimplemented") -} - -func (f *unsupportedShaper) Reset(cidr string) error { - return nil -} - -func (f *unsupportedShaper) ReconcileInterface() error { - return errors.New("unimplemented") -} - -func (f *unsupportedShaper) ReconcileCIDR(cidr string, egress, ingress *resource.Quantity) error { - return errors.New("unimplemented") -} - -func (f *unsupportedShaper) GetCIDRs() ([]string, error) { - return []string{}, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/bandwidth/utils.go b/vendor/github.com/containerd/cri/pkg/server/bandwidth/utils.go deleted file mode 100644 index f90718b6b..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/bandwidth/utils.go +++ /dev/null @@ -1,82 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bandwidth - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/api/resource" -) - -var minRsrc = resource.MustParse("1k") -var maxRsrc = resource.MustParse("1P") - -func validateBandwidthIsReasonable(rsrc *resource.Quantity) error { - if rsrc.Value() < minRsrc.Value() { - return fmt.Errorf("resource is unreasonably small (< 1kbit)") - } - if rsrc.Value() > maxRsrc.Value() { - return fmt.Errorf("resoruce is unreasonably large (> 1Pbit)") - } - return nil -} - -// ExtractPodBandwidthResources extracts the ingress and egress from the given pod annotations -func ExtractPodBandwidthResources(podAnnotations map[string]string) (ingress, egress *resource.Quantity, err error) { - if podAnnotations == nil { - return nil, nil, nil - } - str, found := podAnnotations["kubernetes.io/ingress-bandwidth"] - if found { - ingressValue, err := resource.ParseQuantity(str) - if err != nil { - return nil, nil, err - } - ingress = &ingressValue - if err := validateBandwidthIsReasonable(ingress); err != nil { - return nil, nil, err - } - } - str, found = podAnnotations["kubernetes.io/egress-bandwidth"] - if found { - egressValue, err := resource.ParseQuantity(str) - if err != nil { - return nil, nil, err - } - egress = &egressValue - if err := validateBandwidthIsReasonable(egress); err != nil { - return nil, nil, err - } - } - return ingress, egress, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/cni_conf_syncer.go b/vendor/github.com/containerd/cri/pkg/server/cni_conf_syncer.go deleted file mode 100644 index 03131a9be..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/cni_conf_syncer.go +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "os" - "sync" - - cni "github.com/containerd/go-cni" - "github.com/fsnotify/fsnotify" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// cniNetConfSyncer is used to reload cni network conf triggered by fs change -// events. -type cniNetConfSyncer struct { - // only used for lastSyncStatus - sync.RWMutex - lastSyncStatus error - - watcher *fsnotify.Watcher - confDir string - netPlugin cni.CNI - loadOpts []cni.CNIOpt -} - -// newCNINetConfSyncer creates cni network conf syncer. -func newCNINetConfSyncer(confDir string, netPlugin cni.CNI, loadOpts []cni.CNIOpt) (*cniNetConfSyncer, error) { - watcher, err := fsnotify.NewWatcher() - if err != nil { - return nil, errors.Wrap(err, "failed to create fsnotify watcher") - } - - if err := os.MkdirAll(confDir, 0700); err != nil { - return nil, errors.Wrapf(err, "failed to create cni conf dir=%s for watch", confDir) - } - - if err := watcher.Add(confDir); err != nil { - return nil, errors.Wrapf(err, "failed to watch cni conf dir %s", confDir) - } - - syncer := &cniNetConfSyncer{ - watcher: watcher, - confDir: confDir, - netPlugin: netPlugin, - loadOpts: loadOpts, - } - - if err := syncer.netPlugin.Load(syncer.loadOpts...); err != nil { - logrus.WithError(err).Error("failed to load cni during init, please check CRI plugin status before setting up network for pods") - syncer.updateLastStatus(err) - } - return syncer, nil -} - -// syncLoop monitors any fs change events from cni conf dir and tries to reload -// cni configuration. -func (syncer *cniNetConfSyncer) syncLoop() error { - for { - select { - case event := <-syncer.watcher.Events: - // Only reload config when receiving write/rename/remove - // events - // - // TODO(fuweid): Might only reload target cni config - // files to prevent no-ops. - if event.Op&(fsnotify.Chmod|fsnotify.Create) > 0 { - logrus.Debugf("ignore event from cni conf dir: %s", event) - continue - } - logrus.Debugf("receiving change event from cni conf dir: %s", event) - - lerr := syncer.netPlugin.Load(syncer.loadOpts...) - if lerr != nil { - logrus.WithError(lerr). - Errorf("failed to reload cni configuration after receiving fs change event(%s)", event) - } - syncer.updateLastStatus(lerr) - - case err := <-syncer.watcher.Errors: - if err != nil { - logrus.WithError(err).Error("failed to continue sync cni conf change") - return err - } - } - } -} - -// lastStatus retrieves last sync status. -func (syncer *cniNetConfSyncer) lastStatus() error { - syncer.RLock() - defer syncer.RUnlock() - return syncer.lastSyncStatus -} - -// updateLastStatus will be called after every single cni load. -func (syncer *cniNetConfSyncer) updateLastStatus(err error) { - syncer.Lock() - defer syncer.Unlock() - syncer.lastSyncStatus = err -} - -// stop stops watcher in the syncLoop. -func (syncer *cniNetConfSyncer) stop() error { - return syncer.watcher.Close() -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_attach.go b/vendor/github.com/containerd/cri/pkg/server/container_attach.go deleted file mode 100644 index c8101ff7c..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_attach.go +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "io" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/log" - "github.com/pkg/errors" - "golang.org/x/net/context" - "k8s.io/client-go/tools/remotecommand" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - cio "github.com/containerd/cri/pkg/server/io" -) - -// Attach prepares a streaming endpoint to attach to a running container, and returns the address. -func (c *criService) Attach(ctx context.Context, r *runtime.AttachRequest) (*runtime.AttachResponse, error) { - cntr, err := c.containerStore.Get(r.GetContainerId()) - if err != nil { - return nil, errors.Wrap(err, "failed to find container in store") - } - state := cntr.Status.Get().State() - if state != runtime.ContainerState_CONTAINER_RUNNING { - return nil, errors.Errorf("container is in %s state", criContainerStateToString(state)) - } - return c.streamServer.GetAttach(r) -} - -func (c *criService) attachContainer(ctx context.Context, id string, stdin io.Reader, stdout, stderr io.WriteCloser, - tty bool, resize <-chan remotecommand.TerminalSize) error { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - // Get container from our container store. - cntr, err := c.containerStore.Get(id) - if err != nil { - return errors.Wrapf(err, "failed to find container %q in store", id) - } - id = cntr.ID - - state := cntr.Status.Get().State() - if state != runtime.ContainerState_CONTAINER_RUNNING { - return errors.Errorf("container is in %s state", criContainerStateToString(state)) - } - - task, err := cntr.Container.Task(ctx, nil) - if err != nil { - return errors.Wrap(err, "failed to load task") - } - handleResizing(ctx, resize, func(size remotecommand.TerminalSize) { - if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to resize task %q console", id) - } - }) - - opts := cio.AttachOptions{ - Stdin: stdin, - Stdout: stdout, - Stderr: stderr, - Tty: tty, - StdinOnce: cntr.Config.StdinOnce, - CloseStdin: func() error { - return task.CloseIO(ctx, containerd.WithStdinCloser) - }, - } - // TODO(random-liu): Figure out whether we need to support historical output. - cntr.IO.Attach(opts) - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_create.go b/vendor/github.com/containerd/cri/pkg/server/container_create.go deleted file mode 100644 index 01eac7bc8..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_create.go +++ /dev/null @@ -1,343 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "path/filepath" - "time" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/oci" - "github.com/containerd/typeurl" - "github.com/davecgh/go-spew/spew" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - selinux "github.com/opencontainers/selinux/go-selinux" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - customopts "github.com/containerd/cri/pkg/containerd/opts" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - cio "github.com/containerd/cri/pkg/server/io" - containerstore "github.com/containerd/cri/pkg/store/container" - "github.com/containerd/cri/pkg/util" -) - -func init() { - typeurl.Register(&containerstore.Metadata{}, - "github.com/containerd/cri/pkg/store/container", "Metadata") -} - -// CreateContainer creates a new container in the given PodSandbox. -func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateContainerRequest) (_ *runtime.CreateContainerResponse, retErr error) { - config := r.GetConfig() - log.G(ctx).Debugf("Container config %+v", config) - sandboxConfig := r.GetSandboxConfig() - sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId()) - if err != nil { - return nil, errors.Wrapf(err, "failed to find sandbox id %q", r.GetPodSandboxId()) - } - sandboxID := sandbox.ID - s, err := sandbox.Container.Task(ctx, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to get sandbox container task") - } - sandboxPid := s.Pid() - - // Generate unique id and name for the container and reserve the name. - // Reserve the container name to avoid concurrent `CreateContainer` request creating - // the same container. - id := util.GenerateID() - metadata := config.GetMetadata() - if metadata == nil { - return nil, errors.New("container config must include metadata") - } - containerName := metadata.Name - name := makeContainerName(metadata, sandboxConfig.GetMetadata()) - log.G(ctx).Debugf("Generated id %q for container %q", id, name) - if err = c.containerNameIndex.Reserve(name, id); err != nil { - return nil, errors.Wrapf(err, "failed to reserve container name %q", name) - } - defer func() { - // Release the name if the function returns with an error. - if retErr != nil { - c.containerNameIndex.ReleaseByName(name) - } - }() - - // Create initial internal container metadata. - meta := containerstore.Metadata{ - ID: id, - Name: name, - SandboxID: sandboxID, - Config: config, - } - - // Prepare container image snapshot. For container, the image should have - // been pulled before creating the container, so do not ensure the image. - image, err := c.localResolve(config.GetImage().GetImage()) - if err != nil { - return nil, errors.Wrapf(err, "failed to resolve image %q", config.GetImage().GetImage()) - } - containerdImage, err := c.toContainerdImage(ctx, image) - if err != nil { - return nil, errors.Wrapf(err, "failed to get image from containerd %q", image.ID) - } - - // Run container using the same runtime with sandbox. - sandboxInfo, err := sandbox.Container.Info(ctx) - if err != nil { - return nil, errors.Wrapf(err, "failed to get sandbox %q info", sandboxID) - } - - // Create container root directory. - containerRootDir := c.getContainerRootDir(id) - if err = c.os.MkdirAll(containerRootDir, 0755); err != nil { - return nil, errors.Wrapf(err, "failed to create container root directory %q", - containerRootDir) - } - defer func() { - if retErr != nil { - // Cleanup the container root directory. - if err = c.os.RemoveAll(containerRootDir); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to remove container root directory %q", - containerRootDir) - } - } - }() - volatileContainerRootDir := c.getVolatileContainerRootDir(id) - if err = c.os.MkdirAll(volatileContainerRootDir, 0755); err != nil { - return nil, errors.Wrapf(err, "failed to create volatile container root directory %q", - volatileContainerRootDir) - } - defer func() { - if retErr != nil { - // Cleanup the volatile container root directory. - if err = c.os.RemoveAll(volatileContainerRootDir); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to remove volatile container root directory %q", - volatileContainerRootDir) - } - } - }() - - var volumeMounts []*runtime.Mount - if !c.config.IgnoreImageDefinedVolumes { - // Create container image volumes mounts. - volumeMounts = c.volumeMounts(containerRootDir, config.GetMounts(), &image.ImageSpec.Config) - } else if len(image.ImageSpec.Config.Volumes) != 0 { - log.G(ctx).Debugf("Ignoring volumes defined in image %v because IgnoreImageDefinedVolumes is set", image.ID) - } - - // Generate container mounts. - mounts := c.containerMounts(sandboxID, config) - - ociRuntime, err := c.getSandboxRuntime(sandboxConfig, sandbox.Metadata.RuntimeHandler) - if err != nil { - return nil, errors.Wrap(err, "failed to get sandbox runtime") - } - log.G(ctx).Debugf("Use OCI runtime %+v for sandbox %q and container %q", ociRuntime, sandboxID, id) - - spec, err := c.containerSpec(id, sandboxID, sandboxPid, sandbox.NetNSPath, containerName, config, sandboxConfig, - &image.ImageSpec.Config, append(mounts, volumeMounts...), ociRuntime) - if err != nil { - return nil, errors.Wrapf(err, "failed to generate container %q spec", id) - } - - meta.ProcessLabel = spec.Process.SelinuxLabel - - // handle any KVM based runtime - if err := modifyProcessLabel(ociRuntime.Type, spec); err != nil { - return nil, err - } - - if config.GetLinux().GetSecurityContext().GetPrivileged() { - // If privileged don't set the SELinux label but still record it on the container so - // the unused MCS label can be release later - spec.Process.SelinuxLabel = "" - } - defer func() { - if retErr != nil { - selinux.ReleaseLabel(spec.Process.SelinuxLabel) - } - }() - - log.G(ctx).Debugf("Container %q spec: %#+v", id, spew.NewFormatter(spec)) - - // Set snapshotter before any other options. - opts := []containerd.NewContainerOpts{ - containerd.WithSnapshotter(c.config.ContainerdConfig.Snapshotter), - // Prepare container rootfs. This is always writeable even if - // the container wants a readonly rootfs since we want to give - // the runtime (runc) a chance to modify (e.g. to create mount - // points corresponding to spec.Mounts) before making the - // rootfs readonly (requested by spec.Root.Readonly). - customopts.WithNewSnapshot(id, containerdImage), - } - if len(volumeMounts) > 0 { - mountMap := make(map[string]string) - for _, v := range volumeMounts { - mountMap[filepath.Clean(v.HostPath)] = v.ContainerPath - } - opts = append(opts, customopts.WithVolumes(mountMap)) - } - meta.ImageRef = image.ID - meta.StopSignal = image.ImageSpec.Config.StopSignal - - // Validate log paths and compose full container log path. - if sandboxConfig.GetLogDirectory() != "" && config.GetLogPath() != "" { - meta.LogPath = filepath.Join(sandboxConfig.GetLogDirectory(), config.GetLogPath()) - log.G(ctx).Debugf("Composed container full log path %q using sandbox log dir %q and container log path %q", - meta.LogPath, sandboxConfig.GetLogDirectory(), config.GetLogPath()) - } else { - log.G(ctx).Infof("Logging will be disabled due to empty log paths for sandbox (%q) or container (%q)", - sandboxConfig.GetLogDirectory(), config.GetLogPath()) - } - - containerIO, err := cio.NewContainerIO(id, - cio.WithNewFIFOs(volatileContainerRootDir, config.GetTty(), config.GetStdin())) - if err != nil { - return nil, errors.Wrap(err, "failed to create container io") - } - defer func() { - if retErr != nil { - if err := containerIO.Close(); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to close container io %q", id) - } - } - }() - - specOpts, err := c.containerSpecOpts(config, &image.ImageSpec.Config) - if err != nil { - return nil, errors.Wrap(err, "") - } - - containerLabels := buildLabels(config.Labels, containerKindContainer) - - runtimeOptions, err := getRuntimeOptions(sandboxInfo) - if err != nil { - return nil, errors.Wrap(err, "failed to get runtime options") - } - opts = append(opts, - containerd.WithSpec(spec, specOpts...), - containerd.WithRuntime(sandboxInfo.Runtime.Name, runtimeOptions), - containerd.WithContainerLabels(containerLabels), - containerd.WithContainerExtension(containerMetadataExtension, &meta)) - var cntr containerd.Container - if cntr, err = c.client.NewContainer(ctx, id, opts...); err != nil { - return nil, errors.Wrap(err, "failed to create containerd container") - } - defer func() { - if retErr != nil { - deferCtx, deferCancel := ctrdutil.DeferContext() - defer deferCancel() - if err := cntr.Delete(deferCtx, containerd.WithSnapshotCleanup); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to delete containerd container %q", id) - } - } - }() - - status := containerstore.Status{CreatedAt: time.Now().UnixNano()} - container, err := containerstore.NewContainer(meta, - containerstore.WithStatus(status, containerRootDir), - containerstore.WithContainer(cntr), - containerstore.WithContainerIO(containerIO), - ) - if err != nil { - return nil, errors.Wrapf(err, "failed to create internal container object for %q", id) - } - defer func() { - if retErr != nil { - // Cleanup container checkpoint on error. - if err := container.Delete(); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to cleanup container checkpoint for %q", id) - } - } - }() - - // Add container into container store. - if err := c.containerStore.Add(container); err != nil { - return nil, errors.Wrapf(err, "failed to add container %q into store", id) - } - - return &runtime.CreateContainerResponse{ContainerId: id}, nil -} - -// volumeMounts sets up image volumes for container. Rely on the removal of container -// root directory to do cleanup. Note that image volume will be skipped, if there is criMounts -// specified with the same destination. -func (c *criService) volumeMounts(containerRootDir string, criMounts []*runtime.Mount, config *imagespec.ImageConfig) []*runtime.Mount { - if len(config.Volumes) == 0 { - return nil - } - var mounts []*runtime.Mount - for dst := range config.Volumes { - if isInCRIMounts(dst, criMounts) { - // Skip the image volume, if there is CRI defined volume mapping. - // TODO(random-liu): This should be handled by Kubelet in the future. - // Kubelet should decide what to use for image volume, and also de-duplicate - // the image volume and user mounts. - continue - } - volumeID := util.GenerateID() - src := filepath.Join(containerRootDir, "volumes", volumeID) - // addOCIBindMounts will create these volumes. - mounts = append(mounts, &runtime.Mount{ - ContainerPath: dst, - HostPath: src, - SelinuxRelabel: true, - }) - } - return mounts -} - -// runtimeSpec returns a default runtime spec used in cri-containerd. -func (c *criService) runtimeSpec(id string, baseSpecFile string, opts ...oci.SpecOpts) (*runtimespec.Spec, error) { - // GenerateSpec needs namespace. - ctx := ctrdutil.NamespacedContext() - container := &containers.Container{ID: id} - - if baseSpecFile != "" { - baseSpec, ok := c.baseOCISpecs[baseSpecFile] - if !ok { - return nil, errors.Errorf("can't find base OCI spec %q", baseSpecFile) - } - - spec := oci.Spec{} - if err := util.DeepCopy(&spec, &baseSpec); err != nil { - return nil, errors.Wrap(err, "failed to clone OCI spec") - } - - // Fix up cgroups path - applyOpts := append([]oci.SpecOpts{oci.WithNamespacedCgroup()}, opts...) - - if err := oci.ApplyOpts(ctx, nil, container, &spec, applyOpts...); err != nil { - return nil, errors.Wrap(err, "failed to apply OCI options") - } - - return &spec, nil - } - - spec, err := oci.GenerateSpec(ctx, nil, container, opts...) - if err != nil { - return nil, errors.Wrap(err, "failed to generate spec") - } - - return spec, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_create_unix.go b/vendor/github.com/containerd/cri/pkg/server/container_create_unix.go deleted file mode 100644 index 28863cb0c..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_create_unix.go +++ /dev/null @@ -1,460 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "bufio" - "io" - "os" - "strconv" - "strings" - - "github.com/containerd/cgroups" - "github.com/containerd/containerd/contrib/apparmor" - "github.com/containerd/containerd/contrib/seccomp" - "github.com/containerd/containerd/oci" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - selinux "github.com/opencontainers/selinux/go-selinux" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/annotations" - "github.com/containerd/cri/pkg/config" - customopts "github.com/containerd/cri/pkg/containerd/opts" -) - -const ( - // profileNamePrefix is the prefix for loading profiles on a localhost. Eg. AppArmor localhost/profileName. - profileNamePrefix = "localhost/" // TODO (mikebrow): get localhost/ & runtime/default from CRI kubernetes/kubernetes#51747 - // runtimeDefault indicates that we should use or create a runtime default profile. - runtimeDefault = "runtime/default" - // dockerDefault indicates that we should use or create a docker default profile. - dockerDefault = "docker/default" - // appArmorDefaultProfileName is name to use when creating a default apparmor profile. - appArmorDefaultProfileName = "cri-containerd.apparmor.d" - // unconfinedProfile is a string indicating one should run a pod/containerd without a security profile - unconfinedProfile = "unconfined" - // seccompDefaultProfile is the default seccomp profile. - seccompDefaultProfile = dockerDefault -) - -// containerMounts sets up necessary container system file mounts -// including /dev/shm, /etc/hosts and /etc/resolv.conf. -func (c *criService) containerMounts(sandboxID string, config *runtime.ContainerConfig) []*runtime.Mount { - var mounts []*runtime.Mount - securityContext := config.GetLinux().GetSecurityContext() - if !isInCRIMounts(etcHostname, config.GetMounts()) { - // /etc/hostname is added since 1.1.6, 1.2.4 and 1.3. - // For in-place upgrade, the old sandbox doesn't have the hostname file, - // do not mount this in that case. - // TODO(random-liu): Remove the check and always mount this when - // containerd 1.1 and 1.2 are deprecated. - hostpath := c.getSandboxHostname(sandboxID) - if _, err := c.os.Stat(hostpath); err == nil { - mounts = append(mounts, &runtime.Mount{ - ContainerPath: etcHostname, - HostPath: hostpath, - Readonly: securityContext.GetReadonlyRootfs(), - }) - } - } - - if !isInCRIMounts(etcHosts, config.GetMounts()) { - mounts = append(mounts, &runtime.Mount{ - ContainerPath: etcHosts, - HostPath: c.getSandboxHosts(sandboxID), - Readonly: securityContext.GetReadonlyRootfs(), - }) - } - - // Mount sandbox resolv.config. - // TODO: Need to figure out whether we should always mount it as read-only - if !isInCRIMounts(resolvConfPath, config.GetMounts()) { - mounts = append(mounts, &runtime.Mount{ - ContainerPath: resolvConfPath, - HostPath: c.getResolvPath(sandboxID), - Readonly: securityContext.GetReadonlyRootfs(), - }) - } - - if !isInCRIMounts(devShm, config.GetMounts()) { - sandboxDevShm := c.getSandboxDevShm(sandboxID) - if securityContext.GetNamespaceOptions().GetIpc() == runtime.NamespaceMode_NODE { - sandboxDevShm = devShm - } - mounts = append(mounts, &runtime.Mount{ - ContainerPath: devShm, - HostPath: sandboxDevShm, - Readonly: false, - }) - } - return mounts -} - -func (c *criService) containerSpec(id string, sandboxID string, sandboxPid uint32, netNSPath string, containerName string, - config *runtime.ContainerConfig, sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, - extraMounts []*runtime.Mount, ociRuntime config.Runtime) (_ *runtimespec.Spec, retErr error) { - - specOpts := []oci.SpecOpts{ - customopts.WithoutRunMount, - customopts.WithoutDefaultSecuritySettings, - customopts.WithRelativeRoot(relativeRootfsPath), - customopts.WithProcessArgs(config, imageConfig), - oci.WithDefaultPathEnv, - // this will be set based on the security context below - oci.WithNewPrivileges, - } - if config.GetWorkingDir() != "" { - specOpts = append(specOpts, oci.WithProcessCwd(config.GetWorkingDir())) - } else if imageConfig.WorkingDir != "" { - specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir)) - } - - if config.GetTty() { - specOpts = append(specOpts, oci.WithTTY) - } - - // Add HOSTNAME env. - var ( - err error - hostname = sandboxConfig.GetHostname() - ) - if hostname == "" { - if hostname, err = c.os.Hostname(); err != nil { - return nil, err - } - } - specOpts = append(specOpts, oci.WithEnv([]string{hostnameEnv + "=" + hostname})) - - // Apply envs from image config first, so that envs from container config - // can override them. - env := imageConfig.Env - for _, e := range config.GetEnvs() { - env = append(env, e.GetKey()+"="+e.GetValue()) - } - specOpts = append(specOpts, oci.WithEnv(env)) - - securityContext := config.GetLinux().GetSecurityContext() - labelOptions, err := toLabel(securityContext.GetSelinuxOptions()) - if err != nil { - return nil, err - } - if len(labelOptions) == 0 { - // Use pod level SELinux config - if sandbox, err := c.sandboxStore.Get(sandboxID); err == nil { - labelOptions, err = selinux.DupSecOpt(sandbox.ProcessLabel) - if err != nil { - return nil, err - } - } - } - - processLabel, mountLabel, err := label.InitLabels(labelOptions) - if err != nil { - return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions()) - } - defer func() { - if retErr != nil { - _ = label.ReleaseLabel(processLabel) - } - }() - - specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel)) - - if !c.config.DisableProcMount { - // Apply masked paths if specified. - // If the container is privileged, this will be cleared later on. - specOpts = append(specOpts, oci.WithMaskedPaths(securityContext.GetMaskedPaths())) - - // Apply readonly paths if specified. - // If the container is privileged, this will be cleared later on. - specOpts = append(specOpts, oci.WithReadonlyPaths(securityContext.GetReadonlyPaths())) - } - - if securityContext.GetPrivileged() { - if !sandboxConfig.GetLinux().GetSecurityContext().GetPrivileged() { - return nil, errors.New("no privileged container allowed in sandbox") - } - specOpts = append(specOpts, oci.WithPrivileged) - if !ociRuntime.PrivilegedWithoutHostDevices { - specOpts = append(specOpts, oci.WithHostDevices, oci.WithAllDevicesAllowed) - } else { - // add requested devices by the config as host devices are not automatically added - specOpts = append(specOpts, customopts.WithDevices(c.os, config), customopts.WithCapabilities(securityContext)) - } - } else { // not privileged - specOpts = append(specOpts, customopts.WithDevices(c.os, config), customopts.WithCapabilities(securityContext)) - } - - // Clear all ambient capabilities. The implication of non-root + caps - // is not clearly defined in Kubernetes. - // See https://github.com/kubernetes/kubernetes/issues/56374 - // Keep docker's behavior for now. - specOpts = append(specOpts, - customopts.WithoutAmbientCaps, - customopts.WithSelinuxLabels(processLabel, mountLabel), - ) - - // TODO: Figure out whether we should set no new privilege for sandbox container by default - if securityContext.GetNoNewPrivs() { - specOpts = append(specOpts, oci.WithNoNewPrivileges) - } - // TODO(random-liu): [P1] Set selinux options (privileged or not). - if securityContext.GetReadonlyRootfs() { - specOpts = append(specOpts, oci.WithRootFSReadonly()) - } - - if c.config.DisableCgroup { - specOpts = append(specOpts, customopts.WithDisabledCgroups) - } else { - specOpts = append(specOpts, customopts.WithResources(config.GetLinux().GetResources(), c.config.TolerateMissingHugetlbController, c.config.DisableHugetlbController)) - if sandboxConfig.GetLinux().GetCgroupParent() != "" { - cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id) - specOpts = append(specOpts, oci.WithCgroup(cgroupsPath)) - } - } - - supplementalGroups := securityContext.GetSupplementalGroups() - - for pKey, pValue := range getPassthroughAnnotations(sandboxConfig.Annotations, - ociRuntime.PodAnnotations) { - specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) - } - - for pKey, pValue := range getPassthroughAnnotations(config.Annotations, - ociRuntime.ContainerAnnotations) { - specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) - } - - specOpts = append(specOpts, - customopts.WithOOMScoreAdj(config, c.config.RestrictOOMScoreAdj), - customopts.WithPodNamespaces(securityContext, sandboxPid), - customopts.WithSupplementalGroups(supplementalGroups), - customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer), - customopts.WithAnnotation(annotations.SandboxID, sandboxID), - customopts.WithAnnotation(annotations.ContainerName, containerName), - ) - // cgroupns is used for hiding /sys/fs/cgroup from containers. - // For compatibility, cgroupns is not used when running in cgroup v1 mode or in privileged. - // https://github.com/containers/libpod/issues/4363 - // https://github.com/kubernetes/enhancements/blob/0e409b47497e398b369c281074485c8de129694f/keps/sig-node/20191118-cgroups-v2.md#cgroup-namespace - if cgroups.Mode() == cgroups.Unified && !securityContext.GetPrivileged() { - specOpts = append(specOpts, oci.WithLinuxNamespace( - runtimespec.LinuxNamespace{ - Type: runtimespec.CgroupNamespace, - })) - } - return c.runtimeSpec(id, ociRuntime.BaseRuntimeSpec, specOpts...) -} - -func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageConfig *imagespec.ImageConfig) ([]oci.SpecOpts, error) { - var specOpts []oci.SpecOpts - securityContext := config.GetLinux().GetSecurityContext() - // Set container username. This could only be done by containerd, because it needs - // access to the container rootfs. Pass user name to containerd, and let it overwrite - // the spec for us. - userstr, err := generateUserString( - securityContext.GetRunAsUsername(), - securityContext.GetRunAsUser(), - securityContext.GetRunAsGroup()) - if err != nil { - return nil, errors.Wrap(err, "failed to generate user string") - } - if userstr == "" { - // Lastly, since no user override was passed via CRI try to set via OCI - // Image - userstr = imageConfig.User - } - if userstr != "" { - specOpts = append(specOpts, oci.WithUser(userstr)) - } - - if securityContext.GetRunAsUsername() != "" { - userstr = securityContext.GetRunAsUsername() - } else { - // Even if RunAsUser is not set, we still call `GetValue` to get uid 0. - // Because it is still useful to get additional gids for uid 0. - userstr = strconv.FormatInt(securityContext.GetRunAsUser().GetValue(), 10) - } - specOpts = append(specOpts, customopts.WithAdditionalGIDs(userstr)) - - apparmorSpecOpts, err := generateApparmorSpecOpts( - securityContext.GetApparmorProfile(), - securityContext.GetPrivileged(), - c.apparmorEnabled()) - if err != nil { - return nil, errors.Wrap(err, "failed to generate apparmor spec opts") - } - if apparmorSpecOpts != nil { - specOpts = append(specOpts, apparmorSpecOpts) - } - - seccompSpecOpts, err := c.generateSeccompSpecOpts( - securityContext.GetSeccompProfilePath(), - securityContext.GetPrivileged(), - c.seccompEnabled()) - if err != nil { - return nil, errors.Wrap(err, "failed to generate seccomp spec opts") - } - if seccompSpecOpts != nil { - specOpts = append(specOpts, seccompSpecOpts) - } - return specOpts, nil -} - -// generateSeccompSpecOpts generates containerd SpecOpts for seccomp. -func (c *criService) generateSeccompSpecOpts(seccompProf string, privileged, seccompEnabled bool) (oci.SpecOpts, error) { - if privileged { - // Do not set seccomp profile when container is privileged - return nil, nil - } - if seccompProf == "" { - seccompProf = c.config.UnsetSeccompProfile - } - // Set seccomp profile - if seccompProf == runtimeDefault || seccompProf == dockerDefault { - // use correct default profile (Eg. if not configured otherwise, the default is docker/default) - seccompProf = seccompDefaultProfile - } - if !seccompEnabled { - if seccompProf != "" && seccompProf != unconfinedProfile { - return nil, errors.New("seccomp is not supported") - } - return nil, nil - } - switch seccompProf { - case "", unconfinedProfile: - // Do not set seccomp profile. - return nil, nil - case dockerDefault: - // Note: WithDefaultProfile specOpts must be added after capabilities - return seccomp.WithDefaultProfile(), nil - default: - // Require and Trim default profile name prefix - if !strings.HasPrefix(seccompProf, profileNamePrefix) { - return nil, errors.Errorf("invalid seccomp profile %q", seccompProf) - } - return seccomp.WithProfile(strings.TrimPrefix(seccompProf, profileNamePrefix)), nil - } -} - -// generateApparmorSpecOpts generates containerd SpecOpts for apparmor. -func generateApparmorSpecOpts(apparmorProf string, privileged, apparmorEnabled bool) (oci.SpecOpts, error) { - if !apparmorEnabled { - // Should fail loudly if user try to specify apparmor profile - // but we don't support it. - if apparmorProf != "" && apparmorProf != unconfinedProfile { - return nil, errors.New("apparmor is not supported") - } - return nil, nil - } - switch apparmorProf { - // Based on kubernetes#51746, default apparmor profile should be applied - // for when apparmor is not specified. - case runtimeDefault, "": - if privileged { - // Do not set apparmor profile when container is privileged - return nil, nil - } - // TODO (mikebrow): delete created apparmor default profile - return apparmor.WithDefaultProfile(appArmorDefaultProfileName), nil - case unconfinedProfile: - return nil, nil - default: - // Require and Trim default profile name prefix - if !strings.HasPrefix(apparmorProf, profileNamePrefix) { - return nil, errors.Errorf("invalid apparmor profile %q", apparmorProf) - } - appArmorProfile := strings.TrimPrefix(apparmorProf, profileNamePrefix) - if profileExists, err := appArmorProfileExists(appArmorProfile); !profileExists { - if err != nil { - return nil, errors.Wrap(err, "failed to generate apparmor spec opts") - } - return nil, errors.Errorf("apparmor profile not found %s", appArmorProfile) - } - return apparmor.WithProfile(appArmorProfile), nil - } -} - -// appArmorProfileExists scans apparmor/profiles for the requested profile -func appArmorProfileExists(profile string) (bool, error) { - if profile == "" { - return false, errors.New("nil apparmor profile is not supported") - } - profiles, err := os.Open("/sys/kernel/security/apparmor/profiles") - if err != nil { - return false, err - } - defer profiles.Close() - - rbuff := bufio.NewReader(profiles) - for { - line, err := rbuff.ReadString('\n') - switch err { - case nil: - if strings.HasPrefix(line, profile+" (") { - return true, nil - } - case io.EOF: - return false, nil - default: - return false, err - } - } -} - -// generateUserString generates valid user string based on OCI Image Spec -// v1.0.0. -// -// CRI defines that the following combinations are valid: -// -// (none) -> "" -// username -> username -// username, uid -> username -// username, uid, gid -> username:gid -// username, gid -> username:gid -// uid -> uid -// uid, gid -> uid:gid -// gid -> error -// -// TODO(random-liu): Add group name support in CRI. -func generateUserString(username string, uid, gid *runtime.Int64Value) (string, error) { - var userstr, groupstr string - if uid != nil { - userstr = strconv.FormatInt(uid.GetValue(), 10) - } - if username != "" { - userstr = username - } - if gid != nil { - groupstr = strconv.FormatInt(gid.GetValue(), 10) - } - if userstr == "" { - if groupstr != "" { - return "", errors.Errorf("user group %q is specified without user", groupstr) - } - return "", nil - } - if groupstr != "" { - userstr = userstr + ":" + groupstr - } - return userstr, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_create_windows.go b/vendor/github.com/containerd/cri/pkg/server/container_create_windows.go deleted file mode 100644 index 86a08d89e..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_create_windows.go +++ /dev/null @@ -1,117 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/containerd/containerd/oci" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/annotations" - "github.com/containerd/cri/pkg/config" - customopts "github.com/containerd/cri/pkg/containerd/opts" -) - -// No container mounts for windows. -func (c *criService) containerMounts(sandboxID string, config *runtime.ContainerConfig) []*runtime.Mount { - return nil -} - -func (c *criService) containerSpec(id string, sandboxID string, sandboxPid uint32, netNSPath string, containerName string, - config *runtime.ContainerConfig, sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, - extraMounts []*runtime.Mount, ociRuntime config.Runtime) (*runtimespec.Spec, error) { - specOpts := []oci.SpecOpts{ - customopts.WithProcessArgs(config, imageConfig), - } - if config.GetWorkingDir() != "" { - specOpts = append(specOpts, oci.WithProcessCwd(config.GetWorkingDir())) - } else if imageConfig.WorkingDir != "" { - specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir)) - } - - if config.GetTty() { - specOpts = append(specOpts, oci.WithTTY) - } - - // Apply envs from image config first, so that envs from container config - // can override them. - env := imageConfig.Env - for _, e := range config.GetEnvs() { - env = append(env, e.GetKey()+"="+e.GetValue()) - } - specOpts = append(specOpts, oci.WithEnv(env)) - - specOpts = append(specOpts, - // Clear the root location since hcsshim expects it. - // NOTE: readonly rootfs doesn't work on windows. - customopts.WithoutRoot, - customopts.WithWindowsNetworkNamespace(netNSPath), - oci.WithHostname(sandboxConfig.GetHostname()), - ) - - specOpts = append(specOpts, customopts.WithWindowsMounts(c.os, config, extraMounts)) - - // Start with the image config user and override below if RunAsUsername is not "". - username := imageConfig.User - - windowsConfig := config.GetWindows() - if windowsConfig != nil { - specOpts = append(specOpts, customopts.WithWindowsResources(windowsConfig.GetResources())) - securityCtx := windowsConfig.GetSecurityContext() - if securityCtx != nil { - runAsUser := securityCtx.GetRunAsUsername() - if runAsUser != "" { - username = runAsUser - } - cs := securityCtx.GetCredentialSpec() - if cs != "" { - specOpts = append(specOpts, customopts.WithWindowsCredentialSpec(cs)) - } - } - } - - // There really isn't a good Windows way to verify that the username is available in the - // image as early as here like there is for Linux. Later on in the stack hcsshim - // will handle the behavior of erroring out if the user isn't available in the image - // when trying to run the init process. - specOpts = append(specOpts, oci.WithUser(username)) - - for pKey, pValue := range getPassthroughAnnotations(sandboxConfig.Annotations, - ociRuntime.PodAnnotations) { - specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) - } - - for pKey, pValue := range getPassthroughAnnotations(config.Annotations, - ociRuntime.ContainerAnnotations) { - specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) - } - - specOpts = append(specOpts, - customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer), - customopts.WithAnnotation(annotations.SandboxID, sandboxID), - customopts.WithAnnotation(annotations.ContainerName, containerName), - ) - return c.runtimeSpec(id, ociRuntime.BaseRuntimeSpec, specOpts...) -} - -// No extra spec options needed for windows. -func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageConfig *imagespec.ImageConfig) ([]oci.SpecOpts, error) { - return nil, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_exec.go b/vendor/github.com/containerd/cri/pkg/server/container_exec.go deleted file mode 100644 index ae5498ff7..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_exec.go +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// Exec prepares a streaming endpoint to execute a command in the container, and returns the address. -func (c *criService) Exec(ctx context.Context, r *runtime.ExecRequest) (*runtime.ExecResponse, error) { - cntr, err := c.containerStore.Get(r.GetContainerId()) - if err != nil { - return nil, errors.Wrapf(err, "failed to find container %q in store", r.GetContainerId()) - } - state := cntr.Status.Get().State() - if state != runtime.ContainerState_CONTAINER_RUNNING { - return nil, errors.Errorf("container is in %s state", criContainerStateToString(state)) - } - return c.streamServer.GetExec(r) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_execsync.go b/vendor/github.com/containerd/cri/pkg/server/container_execsync.go deleted file mode 100644 index 1c019f651..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_execsync.go +++ /dev/null @@ -1,211 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "bytes" - "io" - "syscall" - "time" - - "github.com/containerd/containerd" - containerdio "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/oci" - "github.com/pkg/errors" - "golang.org/x/net/context" - "k8s.io/client-go/tools/remotecommand" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - cioutil "github.com/containerd/cri/pkg/ioutil" - cio "github.com/containerd/cri/pkg/server/io" - "github.com/containerd/cri/pkg/util" -) - -// ExecSync executes a command in the container, and returns the stdout output. -// If command exits with a non-zero exit code, an error is returned. -func (c *criService) ExecSync(ctx context.Context, r *runtime.ExecSyncRequest) (*runtime.ExecSyncResponse, error) { - var stdout, stderr bytes.Buffer - exitCode, err := c.execInContainer(ctx, r.GetContainerId(), execOptions{ - cmd: r.GetCmd(), - stdout: cioutil.NewNopWriteCloser(&stdout), - stderr: cioutil.NewNopWriteCloser(&stderr), - timeout: time.Duration(r.GetTimeout()) * time.Second, - }) - if err != nil { - return nil, errors.Wrap(err, "failed to exec in container") - } - - return &runtime.ExecSyncResponse{ - Stdout: stdout.Bytes(), - Stderr: stderr.Bytes(), - ExitCode: int32(*exitCode), - }, nil -} - -// execOptions specifies how to execute command in container. -type execOptions struct { - cmd []string - stdin io.Reader - stdout io.WriteCloser - stderr io.WriteCloser - tty bool - resize <-chan remotecommand.TerminalSize - timeout time.Duration -} - -func (c *criService) execInternal(ctx context.Context, container containerd.Container, id string, opts execOptions) (*uint32, error) { - // Cancel the context before returning to ensure goroutines are stopped. - // This is important, because if `Start` returns error, `Wait` will hang - // forever unless we cancel the context. - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - spec, err := container.Spec(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get container spec") - } - task, err := container.Task(ctx, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to load task") - } - pspec := spec.Process - - pspec.Terminal = opts.tty - if opts.tty { - if err := oci.WithEnv([]string{"TERM=xterm"})(ctx, nil, nil, spec); err != nil { - return nil, errors.Wrap(err, "add TERM env var to spec") - } - } - - pspec.Args = opts.cmd - - if opts.stdout == nil { - opts.stdout = cio.NewDiscardLogger() - } - if opts.stderr == nil { - opts.stderr = cio.NewDiscardLogger() - } - execID := util.GenerateID() - log.G(ctx).Debugf("Generated exec id %q for container %q", execID, id) - volatileRootDir := c.getVolatileContainerRootDir(id) - var execIO *cio.ExecIO - process, err := task.Exec(ctx, execID, pspec, - func(id string) (containerdio.IO, error) { - var err error - execIO, err = cio.NewExecIO(id, volatileRootDir, opts.tty, opts.stdin != nil) - return execIO, err - }, - ) - if err != nil { - return nil, errors.Wrapf(err, "failed to create exec %q", execID) - } - defer func() { - deferCtx, deferCancel := ctrdutil.DeferContext() - defer deferCancel() - if _, err := process.Delete(deferCtx, containerd.WithProcessKill); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to delete exec process %q for container %q", execID, id) - } - }() - - exitCh, err := process.Wait(ctx) - if err != nil { - return nil, errors.Wrapf(err, "failed to wait for process %q", execID) - } - if err := process.Start(ctx); err != nil { - return nil, errors.Wrapf(err, "failed to start exec %q", execID) - } - - handleResizing(ctx, opts.resize, func(size remotecommand.TerminalSize) { - if err := process.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to resize process %q console for container %q", execID, id) - } - }) - - attachDone := execIO.Attach(cio.AttachOptions{ - Stdin: opts.stdin, - Stdout: opts.stdout, - Stderr: opts.stderr, - Tty: opts.tty, - StdinOnce: true, - CloseStdin: func() error { - return process.CloseIO(ctx, containerd.WithStdinCloser) - }, - }) - - execCtx := ctx - if opts.timeout > 0 { - var execCtxCancel context.CancelFunc - execCtx, execCtxCancel = context.WithTimeout(ctx, opts.timeout) - defer execCtxCancel() - } - - select { - case <-execCtx.Done(): - // Ignore the not found error because the process may exit itself before killing. - if err := process.Kill(ctx, syscall.SIGKILL); err != nil && !errdefs.IsNotFound(err) { - return nil, errors.Wrapf(err, "failed to kill exec %q", execID) - } - // Wait for the process to be killed. - exitRes := <-exitCh - log.G(ctx).Infof("Timeout received while waiting for exec process kill %q code %d and error %v", - execID, exitRes.ExitCode(), exitRes.Error()) - <-attachDone - log.G(ctx).Debugf("Stream pipe for exec process %q done", execID) - return nil, errors.Wrapf(execCtx.Err(), "timeout %v exceeded", opts.timeout) - case exitRes := <-exitCh: - code, _, err := exitRes.Result() - log.G(ctx).Infof("Exec process %q exits with exit code %d and error %v", execID, code, err) - if err != nil { - return nil, errors.Wrapf(err, "failed while waiting for exec %q", execID) - } - <-attachDone - log.G(ctx).Debugf("Stream pipe for exec process %q done", execID) - return &code, nil - } -} - -// execInContainer executes a command inside the container synchronously, and -// redirects stdio stream properly. -// This function only returns when the exec process exits, this means that: -// 1) As long as the exec process is running, the goroutine in the cri plugin -// will be running and wait for the exit code; -// 2) `kubectl exec -it` will hang until the exec process exits, even after io -// is detached. This is different from dockershim, which leaves the exec process -// running in background after io is detached. -// https://github.com/kubernetes/kubernetes/blob/v1.15.0/pkg/kubelet/dockershim/exec.go#L127 -// For example, if the `kubectl exec -it` process is killed, IO will be closed. In -// this case, the CRI plugin will still have a goroutine waiting for the exec process -// to exit and log the exit code, but dockershim won't. -func (c *criService) execInContainer(ctx context.Context, id string, opts execOptions) (*uint32, error) { - // Get container from our container store. - cntr, err := c.containerStore.Get(id) - - if err != nil { - return nil, errors.Wrapf(err, "failed to find container %q in store", id) - } - id = cntr.ID - - state := cntr.Status.Get().State() - if state != runtime.ContainerState_CONTAINER_RUNNING { - return nil, errors.Errorf("container is in %s state", criContainerStateToString(state)) - } - - return c.execInternal(ctx, cntr.Container, id, opts) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_list.go b/vendor/github.com/containerd/cri/pkg/server/container_list.go deleted file mode 100644 index c9e88d13d..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_list.go +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "golang.org/x/net/context" - - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - containerstore "github.com/containerd/cri/pkg/store/container" -) - -// ListContainers lists all containers matching the filter. -func (c *criService) ListContainers(ctx context.Context, r *runtime.ListContainersRequest) (*runtime.ListContainersResponse, error) { - // List all containers from store. - containersInStore := c.containerStore.List() - - var containers []*runtime.Container - for _, container := range containersInStore { - containers = append(containers, toCRIContainer(container)) - } - - containers = c.filterCRIContainers(containers, r.GetFilter()) - return &runtime.ListContainersResponse{Containers: containers}, nil -} - -// toCRIContainer converts internal container object into CRI container. -func toCRIContainer(container containerstore.Container) *runtime.Container { - status := container.Status.Get() - return &runtime.Container{ - Id: container.ID, - PodSandboxId: container.SandboxID, - Metadata: container.Config.GetMetadata(), - Image: container.Config.GetImage(), - ImageRef: container.ImageRef, - State: status.State(), - CreatedAt: status.CreatedAt, - Labels: container.Config.GetLabels(), - Annotations: container.Config.GetAnnotations(), - } -} - -func (c *criService) normalizeContainerFilter(filter *runtime.ContainerFilter) { - if cntr, err := c.containerStore.Get(filter.GetId()); err == nil { - filter.Id = cntr.ID - } - if sb, err := c.sandboxStore.Get(filter.GetPodSandboxId()); err == nil { - filter.PodSandboxId = sb.ID - } -} - -// filterCRIContainers filters CRIContainers. -func (c *criService) filterCRIContainers(containers []*runtime.Container, filter *runtime.ContainerFilter) []*runtime.Container { - if filter == nil { - return containers - } - - // The containerd cri plugin supports short ids so long as there is only one - // match. So we do a lookup against the store here if a pod id has been - // included in the filter. - sb := filter.GetPodSandboxId() - if sb != "" { - sandbox, err := c.sandboxStore.Get(sb) - if err == nil { - sb = sandbox.ID - } - } - - c.normalizeContainerFilter(filter) - filtered := []*runtime.Container{} - for _, cntr := range containers { - if filter.GetId() != "" && filter.GetId() != cntr.Id { - continue - } - if sb != "" && sb != cntr.PodSandboxId { - continue - } - if filter.GetState() != nil && filter.GetState().GetState() != cntr.State { - continue - } - if filter.GetLabelSelector() != nil { - match := true - for k, v := range filter.GetLabelSelector() { - got, ok := cntr.Labels[k] - if !ok || got != v { - match = false - break - } - } - if !match { - continue - } - } - filtered = append(filtered, cntr) - } - - return filtered -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_log_reopen.go b/vendor/github.com/containerd/cri/pkg/server/container_log_reopen.go deleted file mode 100644 index b15bb6238..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_log_reopen.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/pkg/errors" - "golang.org/x/net/context" - - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// ReopenContainerLog asks the cri plugin to reopen the stdout/stderr log file for the container. -// This is often called after the log file has been rotated. -func (c *criService) ReopenContainerLog(ctx context.Context, r *runtime.ReopenContainerLogRequest) (*runtime.ReopenContainerLogResponse, error) { - container, err := c.containerStore.Get(r.GetContainerId()) - if err != nil { - return nil, errors.Wrapf(err, "an error occurred when try to find container %q", r.GetContainerId()) - } - - if container.Status.Get().State() != runtime.ContainerState_CONTAINER_RUNNING { - return nil, errors.New("container is not running") - } - - // Create new container logger and replace the existing ones. - stdoutWC, stderrWC, err := c.createContainerLoggers(container.LogPath, container.Config.GetTty()) - if err != nil { - return nil, err - } - oldStdoutWC, oldStderrWC := container.IO.AddOutput("log", stdoutWC, stderrWC) - if oldStdoutWC != nil { - oldStdoutWC.Close() - } - if oldStderrWC != nil { - oldStderrWC.Close() - } - return &runtime.ReopenContainerLogResponse{}, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_remove.go b/vendor/github.com/containerd/cri/pkg/server/container_remove.go deleted file mode 100644 index 6426635dd..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_remove.go +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" -) - -// RemoveContainer removes the container. -func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveContainerRequest) (_ *runtime.RemoveContainerResponse, retErr error) { - container, err := c.containerStore.Get(r.GetContainerId()) - if err != nil { - if err != store.ErrNotExist { - return nil, errors.Wrapf(err, "an error occurred when try to find container %q", r.GetContainerId()) - } - // Do not return error if container metadata doesn't exist. - log.G(ctx).Tracef("RemoveContainer called for container %q that does not exist", r.GetContainerId()) - return &runtime.RemoveContainerResponse{}, nil - } - id := container.ID - - // Forcibly stop the containers if they are in running or unknown state - state := container.Status.Get().State() - if state == runtime.ContainerState_CONTAINER_RUNNING || - state == runtime.ContainerState_CONTAINER_UNKNOWN { - logrus.Infof("Forcibly stopping container %q", id) - if err := c.stopContainer(ctx, container, 0); err != nil { - return nil, errors.Wrapf(err, "failed to forcibly stop container %q", id) - } - - } - - // Set removing state to prevent other start/remove operations against this container - // while it's being removed. - if err := setContainerRemoving(container); err != nil { - return nil, errors.Wrapf(err, "failed to set removing state for container %q", id) - } - defer func() { - if retErr != nil { - // Reset removing if remove failed. - if err := resetContainerRemoving(container); err != nil { - log.G(ctx).WithError(err).Errorf("failed to reset removing state for container %q", id) - } - } - }() - - // NOTE(random-liu): Docker set container to "Dead" state when start removing the - // container so as to avoid start/restart the container again. However, for current - // kubelet implementation, we'll never start a container once we decide to remove it, - // so we don't need the "Dead" state for now. - - // Delete containerd container. - if err := container.Container.Delete(ctx, containerd.WithSnapshotCleanup); err != nil { - if !errdefs.IsNotFound(err) { - return nil, errors.Wrapf(err, "failed to delete containerd container %q", id) - } - log.G(ctx).Tracef("Remove called for containerd container %q that does not exist", id) - } - - // Delete container checkpoint. - if err := container.Delete(); err != nil { - return nil, errors.Wrapf(err, "failed to delete container checkpoint for %q", id) - } - - containerRootDir := c.getContainerRootDir(id) - if err := ensureRemoveAll(ctx, containerRootDir); err != nil { - return nil, errors.Wrapf(err, "failed to remove container root directory %q", - containerRootDir) - } - volatileContainerRootDir := c.getVolatileContainerRootDir(id) - if err := ensureRemoveAll(ctx, volatileContainerRootDir); err != nil { - return nil, errors.Wrapf(err, "failed to remove volatile container root directory %q", - volatileContainerRootDir) - } - - c.containerStore.Delete(id) - - c.containerNameIndex.ReleaseByKey(id) - - return &runtime.RemoveContainerResponse{}, nil -} - -// setContainerRemoving sets the container into removing state. In removing state, the -// container will not be started or removed again. -func setContainerRemoving(container containerstore.Container) error { - return container.Status.Update(func(status containerstore.Status) (containerstore.Status, error) { - // Do not remove container if it's still running or unknown. - if status.State() == runtime.ContainerState_CONTAINER_RUNNING { - return status, errors.New("container is still running, to stop first") - } - if status.State() == runtime.ContainerState_CONTAINER_UNKNOWN { - return status, errors.New("container state is unknown, to stop first") - } - if status.Starting { - return status, errors.New("container is in starting state, can't be removed") - } - if status.Removing { - return status, errors.New("container is already in removing state") - } - status.Removing = true - return status, nil - }) -} - -// resetContainerRemoving resets the container removing state on remove failure. So -// that we could remove the container again. -func resetContainerRemoving(container containerstore.Container) error { - return container.Status.Update(func(status containerstore.Status) (containerstore.Status, error) { - status.Removing = false - return status, nil - }) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_start.go b/vendor/github.com/containerd/cri/pkg/server/container_start.go deleted file mode 100644 index d00eb3d8e..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_start.go +++ /dev/null @@ -1,222 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "io" - "time" - - "github.com/containerd/containerd" - containerdio "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/containerd/nri" - v1 "github.com/containerd/nri/types/v1" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - cioutil "github.com/containerd/cri/pkg/ioutil" - cio "github.com/containerd/cri/pkg/server/io" - containerstore "github.com/containerd/cri/pkg/store/container" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -// StartContainer starts the container. -func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContainerRequest) (retRes *runtime.StartContainerResponse, retErr error) { - cntr, err := c.containerStore.Get(r.GetContainerId()) - if err != nil { - return nil, errors.Wrapf(err, "an error occurred when try to find container %q", r.GetContainerId()) - } - - id := cntr.ID - meta := cntr.Metadata - container := cntr.Container - config := meta.Config - - // Set starting state to prevent other start/remove operations against this container - // while it's being started. - if err := setContainerStarting(cntr); err != nil { - return nil, errors.Wrapf(err, "failed to set starting state for container %q", id) - } - defer func() { - if retErr != nil { - // Set container to exited if fail to start. - if err := cntr.Status.UpdateSync(func(status containerstore.Status) (containerstore.Status, error) { - status.Pid = 0 - status.FinishedAt = time.Now().UnixNano() - status.ExitCode = errorStartExitCode - status.Reason = errorStartReason - status.Message = retErr.Error() - return status, nil - }); err != nil { - log.G(ctx).WithError(err).Errorf("failed to set start failure state for container %q", id) - } - } - if err := resetContainerStarting(cntr); err != nil { - log.G(ctx).WithError(err).Errorf("failed to reset starting state for container %q", id) - } - }() - - // Get sandbox config from sandbox store. - sandbox, err := c.sandboxStore.Get(meta.SandboxID) - if err != nil { - return nil, errors.Wrapf(err, "sandbox %q not found", meta.SandboxID) - } - sandboxID := meta.SandboxID - if sandbox.Status.Get().State != sandboxstore.StateReady { - return nil, errors.Errorf("sandbox container %q is not running", sandboxID) - } - - ioCreation := func(id string) (_ containerdio.IO, err error) { - stdoutWC, stderrWC, err := c.createContainerLoggers(meta.LogPath, config.GetTty()) - if err != nil { - return nil, errors.Wrap(err, "failed to create container loggers") - } - cntr.IO.AddOutput("log", stdoutWC, stderrWC) - cntr.IO.Pipe() - return cntr.IO, nil - } - - ctrInfo, err := container.Info(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get container info") - } - - taskOpts := c.taskOpts(ctrInfo.Runtime.Name) - task, err := container.NewTask(ctx, ioCreation, taskOpts...) - if err != nil { - return nil, errors.Wrap(err, "failed to create containerd task") - } - defer func() { - if retErr != nil { - deferCtx, deferCancel := ctrdutil.DeferContext() - defer deferCancel() - // It's possible that task is deleted by event monitor. - if _, err := task.Delete(deferCtx, WithNRISandboxDelete(sandboxID), containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - log.G(ctx).WithError(err).Errorf("Failed to delete containerd task %q", id) - } - } - }() - - // wait is a long running background request, no timeout needed. - exitCh, err := task.Wait(ctrdutil.NamespacedContext()) - if err != nil { - return nil, errors.Wrap(err, "failed to wait for containerd task") - } - nric, err := nri.New() - if err != nil { - log.G(ctx).WithError(err).Error("unable to create nri client") - } - if nric != nil { - nriSB := &nri.Sandbox{ - ID: sandboxID, - } - if _, err := nric.InvokeWithSandbox(ctx, task, v1.Create, nriSB); err != nil { - return nil, errors.Wrap(err, "nri invoke") - } - } - - // Start containerd task. - if err := task.Start(ctx); err != nil { - return nil, errors.Wrapf(err, "failed to start containerd task %q", id) - } - - // Update container start timestamp. - if err := cntr.Status.UpdateSync(func(status containerstore.Status) (containerstore.Status, error) { - status.Pid = task.Pid() - status.StartedAt = time.Now().UnixNano() - return status, nil - }); err != nil { - return nil, errors.Wrapf(err, "failed to update container %q state", id) - } - - // start the monitor after updating container state, this ensures that - // event monitor receives the TaskExit event and update container state - // after this. - c.eventMonitor.startExitMonitor(context.Background(), id, task.Pid(), exitCh) - - return &runtime.StartContainerResponse{}, nil -} - -// setContainerStarting sets the container into starting state. In starting state, the -// container will not be removed or started again. -func setContainerStarting(container containerstore.Container) error { - return container.Status.Update(func(status containerstore.Status) (containerstore.Status, error) { - // Return error if container is not in created state. - if status.State() != runtime.ContainerState_CONTAINER_CREATED { - return status, errors.Errorf("container is in %s state", criContainerStateToString(status.State())) - } - // Do not start the container when there is a removal in progress. - if status.Removing { - return status, errors.New("container is in removing state, can't be started") - } - if status.Starting { - return status, errors.New("container is already in starting state") - } - status.Starting = true - return status, nil - }) -} - -// resetContainerStarting resets the container starting state on start failure. So -// that we could remove the container later. -func resetContainerStarting(container containerstore.Container) error { - return container.Status.Update(func(status containerstore.Status) (containerstore.Status, error) { - status.Starting = false - return status, nil - }) -} - -// createContainerLoggers creates container loggers and return write closer for stdout and stderr. -func (c *criService) createContainerLoggers(logPath string, tty bool) (stdout io.WriteCloser, stderr io.WriteCloser, err error) { - if logPath != "" { - // Only generate container log when log path is specified. - f, err := openLogFile(logPath) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to create and open log file") - } - defer func() { - if err != nil { - f.Close() - } - }() - var stdoutCh, stderrCh <-chan struct{} - wc := cioutil.NewSerialWriteCloser(f) - stdout, stdoutCh = cio.NewCRILogger(logPath, wc, cio.Stdout, c.config.MaxContainerLogLineSize) - // Only redirect stderr when there is no tty. - if !tty { - stderr, stderrCh = cio.NewCRILogger(logPath, wc, cio.Stderr, c.config.MaxContainerLogLineSize) - } - go func() { - if stdoutCh != nil { - <-stdoutCh - } - if stderrCh != nil { - <-stderrCh - } - logrus.Debugf("Finish redirecting log file %q, closing it", logPath) - f.Close() - }() - } else { - stdout = cio.NewDiscardLogger() - stderr = cio.NewDiscardLogger() - } - return -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_stats.go b/vendor/github.com/containerd/cri/pkg/server/container_stats.go deleted file mode 100644 index 22607cdd8..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_stats.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - tasks "github.com/containerd/containerd/api/services/tasks/v1" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// ContainerStats returns stats of the container. If the container does not -// exist, the call returns an error. -func (c *criService) ContainerStats(ctx context.Context, in *runtime.ContainerStatsRequest) (*runtime.ContainerStatsResponse, error) { - cntr, err := c.containerStore.Get(in.GetContainerId()) - if err != nil { - return nil, errors.Wrap(err, "failed to find container") - } - request := &tasks.MetricsRequest{Filters: []string{"id==" + cntr.ID}} - resp, err := c.client.TaskService().Metrics(ctx, request) - if err != nil { - return nil, errors.Wrap(err, "failed to fetch metrics for task") - } - if len(resp.Metrics) != 1 { - return nil, errors.Errorf("unexpected metrics response: %+v", resp.Metrics) - } - - cs, err := c.containerMetrics(cntr.Metadata, resp.Metrics[0]) - if err != nil { - return nil, errors.Wrap(err, "failed to decode container metrics") - } - return &runtime.ContainerStatsResponse{Stats: cs}, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_stats_list.go b/vendor/github.com/containerd/cri/pkg/server/container_stats_list.go deleted file mode 100644 index 0a9be8741..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_stats_list.go +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - tasks "github.com/containerd/containerd/api/services/tasks/v1" - "github.com/containerd/containerd/api/types" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - containerstore "github.com/containerd/cri/pkg/store/container" -) - -// ListContainerStats returns stats of all running containers. -func (c *criService) ListContainerStats( - ctx context.Context, - in *runtime.ListContainerStatsRequest, -) (*runtime.ListContainerStatsResponse, error) { - request, containers, err := c.buildTaskMetricsRequest(in) - if err != nil { - return nil, errors.Wrap(err, "failed to build metrics request") - } - resp, err := c.client.TaskService().Metrics(ctx, &request) - if err != nil { - return nil, errors.Wrap(err, "failed to fetch metrics for tasks") - } - criStats, err := c.toCRIContainerStats(resp.Metrics, containers) - if err != nil { - return nil, errors.Wrap(err, "failed to convert to cri containerd stats format") - } - return criStats, nil -} - -func (c *criService) toCRIContainerStats( - stats []*types.Metric, - containers []containerstore.Container, -) (*runtime.ListContainerStatsResponse, error) { - statsMap := make(map[string]*types.Metric) - for _, stat := range stats { - statsMap[stat.ID] = stat - } - containerStats := new(runtime.ListContainerStatsResponse) - for _, cntr := range containers { - cs, err := c.containerMetrics(cntr.Metadata, statsMap[cntr.ID]) - if err != nil { - return nil, errors.Wrapf(err, "failed to decode container metrics for %q", cntr.ID) - } - containerStats.Stats = append(containerStats.Stats, cs) - } - return containerStats, nil -} - -func (c *criService) normalizeContainerStatsFilter(filter *runtime.ContainerStatsFilter) { - if cntr, err := c.containerStore.Get(filter.GetId()); err == nil { - filter.Id = cntr.ID - } - if sb, err := c.sandboxStore.Get(filter.GetPodSandboxId()); err == nil { - filter.PodSandboxId = sb.ID - } -} - -// buildTaskMetricsRequest constructs a tasks.MetricsRequest based on -// the information in the stats request and the containerStore -func (c *criService) buildTaskMetricsRequest( - r *runtime.ListContainerStatsRequest, -) (tasks.MetricsRequest, []containerstore.Container, error) { - var req tasks.MetricsRequest - if r.GetFilter() == nil { - return req, nil, nil - } - c.normalizeContainerStatsFilter(r.GetFilter()) - var containers []containerstore.Container - for _, cntr := range c.containerStore.List() { - if r.GetFilter().GetId() != "" && cntr.ID != r.GetFilter().GetId() { - continue - } - if r.GetFilter().GetPodSandboxId() != "" && cntr.SandboxID != r.GetFilter().GetPodSandboxId() { - continue - } - if r.GetFilter().GetLabelSelector() != nil && - !matchLabelSelector(r.GetFilter().GetLabelSelector(), cntr.Config.GetLabels()) { - continue - } - containers = append(containers, cntr) - req.Filters = append(req.Filters, "id=="+cntr.ID) - } - return req, containers, nil -} - -func matchLabelSelector(selector, labels map[string]string) bool { - for k, v := range selector { - if val, ok := labels[k]; ok { - if v != val { - return false - } - } else { - return false - } - } - return true -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_stats_list_unix.go b/vendor/github.com/containerd/cri/pkg/server/container_stats_list_unix.go deleted file mode 100644 index ad398bc7a..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_stats_list_unix.go +++ /dev/null @@ -1,129 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "fmt" - - "github.com/containerd/containerd/api/types" - v1 "github.com/containerd/containerd/metrics/types/v1" - v2 "github.com/containerd/containerd/metrics/types/v2" - "github.com/containerd/typeurl" - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - containerstore "github.com/containerd/cri/pkg/store/container" -) - -func (c *criService) containerMetrics( - meta containerstore.Metadata, - stats *types.Metric, -) (*runtime.ContainerStats, error) { - var cs runtime.ContainerStats - var usedBytes, inodesUsed uint64 - sn, err := c.snapshotStore.Get(meta.ID) - // If snapshotstore doesn't have cached snapshot information - // set WritableLayer usage to zero - if err == nil { - usedBytes = sn.Size - inodesUsed = sn.Inodes - } - cs.WritableLayer = &runtime.FilesystemUsage{ - Timestamp: sn.Timestamp, - FsId: &runtime.FilesystemIdentifier{ - Mountpoint: c.imageFSPath, - }, - UsedBytes: &runtime.UInt64Value{Value: usedBytes}, - InodesUsed: &runtime.UInt64Value{Value: inodesUsed}, - } - cs.Attributes = &runtime.ContainerAttributes{ - Id: meta.ID, - Metadata: meta.Config.GetMetadata(), - Labels: meta.Config.GetLabels(), - Annotations: meta.Config.GetAnnotations(), - } - - if stats != nil { - s, err := typeurl.UnmarshalAny(stats.Data) - if err != nil { - return nil, errors.Wrap(err, "failed to extract container metrics") - } - switch metrics := s.(type) { - case *v1.Metrics: - if metrics.CPU != nil && metrics.CPU.Usage != nil { - cs.Cpu = &runtime.CpuUsage{ - Timestamp: stats.Timestamp.UnixNano(), - UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.Usage.Total}, - } - } - if metrics.Memory != nil && metrics.Memory.Usage != nil { - cs.Memory = &runtime.MemoryUsage{ - Timestamp: stats.Timestamp.UnixNano(), - WorkingSetBytes: &runtime.UInt64Value{ - Value: getWorkingSet(metrics.Memory), - }, - } - } - case *v2.Metrics: - if metrics.CPU != nil { - cs.Cpu = &runtime.CpuUsage{ - Timestamp: stats.Timestamp.UnixNano(), - UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.UsageUsec * 1000}, - } - } - if metrics.Memory != nil { - cs.Memory = &runtime.MemoryUsage{ - Timestamp: stats.Timestamp.UnixNano(), - WorkingSetBytes: &runtime.UInt64Value{ - Value: getWorkingSetV2(metrics.Memory), - }, - } - } - default: - return &cs, errors.New(fmt.Sprintf("unxpected metrics type: %v", metrics)) - } - } - - return &cs, nil -} - -// getWorkingSet calculates workingset memory from cgroup memory stats. -// The caller should make sure memory is not nil. -// workingset = usage - total_inactive_file -func getWorkingSet(memory *v1.MemoryStat) uint64 { - if memory.Usage == nil { - return 0 - } - var workingSet uint64 - if memory.TotalInactiveFile < memory.Usage.Usage { - workingSet = memory.Usage.Usage - memory.TotalInactiveFile - } - return workingSet -} - -// getWorkingSetV2 calculates workingset memory from cgroupv2 memory stats. -// The caller should make sure memory is not nil. -// workingset = usage - inactive_file -func getWorkingSetV2(memory *v2.MemoryStat) uint64 { - var workingSet uint64 - if memory.InactiveFile < memory.Usage { - workingSet = memory.Usage - memory.InactiveFile - } - return workingSet -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_stats_list_windows.go b/vendor/github.com/containerd/cri/pkg/server/container_stats_list_windows.go deleted file mode 100644 index 4bd3b64c1..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_stats_list_windows.go +++ /dev/null @@ -1,84 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - wstats "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/stats" - "github.com/containerd/containerd/api/types" - "github.com/containerd/typeurl" - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - containerstore "github.com/containerd/cri/pkg/store/container" -) - -func (c *criService) containerMetrics( - meta containerstore.Metadata, - stats *types.Metric, -) (*runtime.ContainerStats, error) { - var cs runtime.ContainerStats - var usedBytes, inodesUsed uint64 - sn, err := c.snapshotStore.Get(meta.ID) - // If snapshotstore doesn't have cached snapshot information - // set WritableLayer usage to zero - if err == nil { - usedBytes = sn.Size - inodesUsed = sn.Inodes - } - cs.WritableLayer = &runtime.FilesystemUsage{ - Timestamp: sn.Timestamp, - FsId: &runtime.FilesystemIdentifier{ - Mountpoint: c.imageFSPath, - }, - UsedBytes: &runtime.UInt64Value{Value: usedBytes}, - InodesUsed: &runtime.UInt64Value{Value: inodesUsed}, - } - cs.Attributes = &runtime.ContainerAttributes{ - Id: meta.ID, - Metadata: meta.Config.GetMetadata(), - Labels: meta.Config.GetLabels(), - Annotations: meta.Config.GetAnnotations(), - } - - if stats != nil { - s, err := typeurl.UnmarshalAny(stats.Data) - if err != nil { - return nil, errors.Wrap(err, "failed to extract container metrics") - } - wstats := s.(*wstats.Statistics).GetWindows() - if wstats == nil { - return nil, errors.New("windows stats is empty") - } - if wstats.Processor != nil { - cs.Cpu = &runtime.CpuUsage{ - Timestamp: wstats.Timestamp.UnixNano(), - UsageCoreNanoSeconds: &runtime.UInt64Value{Value: wstats.Processor.TotalRuntimeNS}, - } - } - if wstats.Memory != nil { - cs.Memory = &runtime.MemoryUsage{ - Timestamp: wstats.Timestamp.UnixNano(), - WorkingSetBytes: &runtime.UInt64Value{ - Value: wstats.Memory.MemoryUsagePrivateWorkingSetBytes, - }, - } - } - } - return &cs, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_status.go b/vendor/github.com/containerd/cri/pkg/server/container_status.go deleted file mode 100644 index aeeb76db3..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_status.go +++ /dev/null @@ -1,173 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "encoding/json" - - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" -) - -// ContainerStatus inspects the container and returns the status. -func (c *criService) ContainerStatus(ctx context.Context, r *runtime.ContainerStatusRequest) (*runtime.ContainerStatusResponse, error) { - container, err := c.containerStore.Get(r.GetContainerId()) - if err != nil { - return nil, errors.Wrapf(err, "an error occurred when try to find container %q", r.GetContainerId()) - } - - // TODO(random-liu): Clean up the following logic in CRI. - // Current assumption: - // * ImageSpec in container config is image ID. - // * ImageSpec in container status is image tag. - // * ImageRef in container status is repo digest. - spec := container.Config.GetImage() - imageRef := container.ImageRef - image, err := c.imageStore.Get(imageRef) - if err != nil { - if err != store.ErrNotExist { - return nil, errors.Wrapf(err, "failed to get image %q", imageRef) - } - } else { - repoTags, repoDigests := parseImageReferences(image.References) - if len(repoTags) > 0 { - // Based on current behavior of dockershim, this field should be - // image tag. - spec = &runtime.ImageSpec{Image: repoTags[0]} - } - if len(repoDigests) > 0 { - // Based on the CRI definition, this field will be consumed by user. - imageRef = repoDigests[0] - } - } - status := toCRIContainerStatus(container, spec, imageRef) - if status.GetCreatedAt() == 0 { - // CRI doesn't allow CreatedAt == 0. - info, err := container.Container.Info(ctx) - if err != nil { - return nil, errors.Wrapf(err, "failed to get CreatedAt in %q state", status.State) - } - status.CreatedAt = info.CreatedAt.UnixNano() - } - - info, err := toCRIContainerInfo(ctx, container, r.GetVerbose()) - if err != nil { - return nil, errors.Wrap(err, "failed to get verbose container info") - } - - return &runtime.ContainerStatusResponse{ - Status: status, - Info: info, - }, nil -} - -// toCRIContainerStatus converts internal container object to CRI container status. -func toCRIContainerStatus(container containerstore.Container, spec *runtime.ImageSpec, imageRef string) *runtime.ContainerStatus { - meta := container.Metadata - status := container.Status.Get() - reason := status.Reason - if status.State() == runtime.ContainerState_CONTAINER_EXITED && reason == "" { - if status.ExitCode == 0 { - reason = completeExitReason - } else { - reason = errorExitReason - } - } - - return &runtime.ContainerStatus{ - Id: meta.ID, - Metadata: meta.Config.GetMetadata(), - State: status.State(), - CreatedAt: status.CreatedAt, - StartedAt: status.StartedAt, - FinishedAt: status.FinishedAt, - ExitCode: status.ExitCode, - Image: spec, - ImageRef: imageRef, - Reason: reason, - Message: status.Message, - Labels: meta.Config.GetLabels(), - Annotations: meta.Config.GetAnnotations(), - Mounts: meta.Config.GetMounts(), - LogPath: meta.LogPath, - } -} - -// ContainerInfo is extra information for a container. -type ContainerInfo struct { - // TODO(random-liu): Add sandboxID in CRI container status. - SandboxID string `json:"sandboxID"` - Pid uint32 `json:"pid"` - Removing bool `json:"removing"` - SnapshotKey string `json:"snapshotKey"` - Snapshotter string `json:"snapshotter"` - RuntimeType string `json:"runtimeType"` - RuntimeOptions interface{} `json:"runtimeOptions"` - Config *runtime.ContainerConfig `json:"config"` - RuntimeSpec *runtimespec.Spec `json:"runtimeSpec"` -} - -// toCRIContainerInfo converts internal container object information to CRI container status response info map. -func toCRIContainerInfo(ctx context.Context, container containerstore.Container, verbose bool) (map[string]string, error) { - if !verbose { - return nil, nil - } - - meta := container.Metadata - status := container.Status.Get() - - // TODO(random-liu): Change CRI status info to use array instead of map. - ci := &ContainerInfo{ - SandboxID: container.SandboxID, - Pid: status.Pid, - Removing: status.Removing, - Config: meta.Config, - } - - var err error - ci.RuntimeSpec, err = container.Container.Spec(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get container runtime spec") - } - - ctrInfo, err := container.Container.Info(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get container info") - } - ci.SnapshotKey = ctrInfo.SnapshotKey - ci.Snapshotter = ctrInfo.Snapshotter - - runtimeOptions, err := getRuntimeOptions(ctrInfo) - if err != nil { - return nil, errors.Wrap(err, "failed to get runtime options") - } - ci.RuntimeType = ctrInfo.Runtime.Name - ci.RuntimeOptions = runtimeOptions - - infoBytes, err := json.Marshal(ci) - if err != nil { - return nil, errors.Wrapf(err, "failed to marshal info %v", ci) - } - return map[string]string{ - "info": string(infoBytes), - }, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_stop.go b/vendor/github.com/containerd/cri/pkg/server/container_stop.go deleted file mode 100644 index 92075d6b6..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_stop.go +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "syscall" - "time" - - "github.com/containerd/containerd" - eventtypes "github.com/containerd/containerd/api/events" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" -) - -// StopContainer stops a running container with a grace period (i.e., timeout). -func (c *criService) StopContainer(ctx context.Context, r *runtime.StopContainerRequest) (*runtime.StopContainerResponse, error) { - // Get container config from container store. - container, err := c.containerStore.Get(r.GetContainerId()) - if err != nil { - return nil, errors.Wrapf(err, "an error occurred when try to find container %q", r.GetContainerId()) - } - - if err := c.stopContainer(ctx, container, time.Duration(r.GetTimeout())*time.Second); err != nil { - return nil, err - } - - return &runtime.StopContainerResponse{}, nil -} - -// stopContainer stops a container based on the container metadata. -func (c *criService) stopContainer(ctx context.Context, container containerstore.Container, timeout time.Duration) error { - id := container.ID - - // Return without error if container is not running. This makes sure that - // stop only takes real action after the container is started. - state := container.Status.Get().State() - if state != runtime.ContainerState_CONTAINER_RUNNING && - state != runtime.ContainerState_CONTAINER_UNKNOWN { - log.G(ctx).Infof("Container to stop %q must be in running or unknown state, current state %q", - id, criContainerStateToString(state)) - return nil - } - - task, err := container.Container.Task(ctx, nil) - if err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrapf(err, "failed to get task for container %q", id) - } - // Don't return for unknown state, some cleanup needs to be done. - if state == runtime.ContainerState_CONTAINER_UNKNOWN { - return cleanupUnknownContainer(ctx, id, container) - } - return nil - } - - // Handle unknown state. - if state == runtime.ContainerState_CONTAINER_UNKNOWN { - // Start an exit handler for containers in unknown state. - waitCtx, waitCancel := context.WithCancel(ctrdutil.NamespacedContext()) - defer waitCancel() - exitCh, err := task.Wait(waitCtx) - if err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrapf(err, "failed to wait for task for %q", id) - } - return cleanupUnknownContainer(ctx, id, container) - } - - exitCtx, exitCancel := context.WithCancel(context.Background()) - stopCh := c.eventMonitor.startExitMonitor(exitCtx, id, task.Pid(), exitCh) - defer func() { - exitCancel() - // This ensures that exit monitor is stopped before - // `Wait` is cancelled, so no exit event is generated - // because of the `Wait` cancellation. - <-stopCh - }() - } - - // We only need to kill the task. The event handler will Delete the - // task from containerd after it handles the Exited event. - if timeout > 0 { - stopSignal := "SIGTERM" - if container.StopSignal != "" { - stopSignal = container.StopSignal - } else { - // The image may have been deleted, and the `StopSignal` field is - // just introduced to handle that. - // However, for containers created before the `StopSignal` field is - // introduced, still try to get the stop signal from the image config. - // If the image has been deleted, logging an error and using the - // default SIGTERM is still better than returning error and leaving - // the container unstoppable. (See issue #990) - // TODO(random-liu): Remove this logic when containerd 1.2 is deprecated. - image, err := c.imageStore.Get(container.ImageRef) - if err != nil { - if err != store.ErrNotExist { - return errors.Wrapf(err, "failed to get image %q", container.ImageRef) - } - log.G(ctx).Warningf("Image %q not found, stop container with signal %q", container.ImageRef, stopSignal) - } else { - if image.ImageSpec.Config.StopSignal != "" { - stopSignal = image.ImageSpec.Config.StopSignal - } - } - } - sig, err := containerd.ParseSignal(stopSignal) - if err != nil { - return errors.Wrapf(err, "failed to parse stop signal %q", stopSignal) - } - log.G(ctx).Infof("Stop container %q with signal %v", id, sig) - if err = task.Kill(ctx, sig); err != nil && !errdefs.IsNotFound(err) { - return errors.Wrapf(err, "failed to stop container %q", id) - } - - sigTermCtx, sigTermCtxCancel := context.WithTimeout(ctx, timeout) - defer sigTermCtxCancel() - err = c.waitContainerStop(sigTermCtx, container) - if err == nil { - // Container stopped on first signal no need for SIGKILL - return nil - } - // If the parent context was cancelled or exceeded return immediately - if ctx.Err() != nil { - return ctx.Err() - } - // sigTermCtx was exceeded. Send SIGKILL - log.G(ctx).Debugf("Stop container %q with signal %v timed out", id, sig) - } - - log.G(ctx).Infof("Kill container %q", id) - if err = task.Kill(ctx, syscall.SIGKILL); err != nil && !errdefs.IsNotFound(err) { - return errors.Wrapf(err, "failed to kill container %q", id) - } - - // Wait for a fixed timeout until container stop is observed by event monitor. - err = c.waitContainerStop(ctx, container) - if err != nil { - return errors.Wrapf(err, "an error occurs during waiting for container %q to be killed", id) - } - return nil -} - -// waitContainerStop waits for container to be stopped until context is -// cancelled or the context deadline is exceeded. -func (c *criService) waitContainerStop(ctx context.Context, container containerstore.Container) error { - select { - case <-ctx.Done(): - return errors.Wrapf(ctx.Err(), "wait container %q", container.ID) - case <-container.Stopped(): - return nil - } -} - -// cleanupUnknownContainer cleanup stopped container in unknown state. -func cleanupUnknownContainer(ctx context.Context, id string, cntr containerstore.Container) error { - // Reuse handleContainerExit to do the cleanup. - return handleContainerExit(ctx, &eventtypes.TaskExit{ - ContainerID: id, - ID: id, - Pid: 0, - ExitStatus: unknownExitCode, - ExitedAt: time.Now(), - }, cntr) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_update_resources_unix.go b/vendor/github.com/containerd/cri/pkg/server/container_update_resources_unix.go deleted file mode 100644 index 23e0d409b..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_update_resources_unix.go +++ /dev/null @@ -1,150 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - gocontext "context" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/containerd/typeurl" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/containerd/opts" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - containerstore "github.com/containerd/cri/pkg/store/container" - "github.com/containerd/cri/pkg/util" -) - -// UpdateContainerResources updates ContainerConfig of the container. -func (c *criService) UpdateContainerResources(ctx context.Context, r *runtime.UpdateContainerResourcesRequest) (retRes *runtime.UpdateContainerResourcesResponse, retErr error) { - container, err := c.containerStore.Get(r.GetContainerId()) - if err != nil { - return nil, errors.Wrap(err, "failed to find container") - } - // Update resources in status update transaction, so that: - // 1) There won't be race condition with container start. - // 2) There won't be concurrent resource update to the same container. - if err := container.Status.Update(func(status containerstore.Status) (containerstore.Status, error) { - return status, c.updateContainerResources(ctx, container, r.GetLinux(), status) - }); err != nil { - return nil, errors.Wrap(err, "failed to update resources") - } - return &runtime.UpdateContainerResourcesResponse{}, nil -} - -func (c *criService) updateContainerResources(ctx context.Context, - cntr containerstore.Container, - resources *runtime.LinuxContainerResources, - status containerstore.Status) (retErr error) { - id := cntr.ID - // Do not update the container when there is a removal in progress. - if status.Removing { - return errors.Errorf("container %q is in removing state", id) - } - - // Update container spec. If the container is not started yet, updating - // spec makes sure that the resource limits are correct when start; - // if the container is already started, updating spec is still required, - // the spec will become our source of truth for resource limits. - oldSpec, err := cntr.Container.Spec(ctx) - if err != nil { - return errors.Wrap(err, "failed to get container spec") - } - newSpec, err := updateOCILinuxResource(ctx, oldSpec, resources, - c.config.TolerateMissingHugetlbController, c.config.DisableHugetlbController) - if err != nil { - return errors.Wrap(err, "failed to update resource in spec") - } - - if err := updateContainerSpec(ctx, cntr.Container, newSpec); err != nil { - return err - } - defer func() { - if retErr != nil { - deferCtx, deferCancel := ctrdutil.DeferContext() - defer deferCancel() - // Reset spec on error. - if err := updateContainerSpec(deferCtx, cntr.Container, oldSpec); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to update spec %+v for container %q", oldSpec, id) - } - } - }() - - // If container is not running, only update spec is enough, new resource - // limit will be applied when container start. - if status.State() != runtime.ContainerState_CONTAINER_RUNNING { - return nil - } - - task, err := cntr.Container.Task(ctx, nil) - if err != nil { - if errdefs.IsNotFound(err) { - // Task exited already. - return nil - } - return errors.Wrap(err, "failed to get task") - } - // newSpec.Linux won't be nil - if err := task.Update(ctx, containerd.WithResources(newSpec.Linux.Resources)); err != nil { - if errdefs.IsNotFound(err) { - // Task exited already. - return nil - } - return errors.Wrap(err, "failed to update resources") - } - return nil -} - -// updateContainerSpec updates container spec. -func updateContainerSpec(ctx context.Context, cntr containerd.Container, spec *runtimespec.Spec) error { - any, err := typeurl.MarshalAny(spec) - if err != nil { - return errors.Wrapf(err, "failed to marshal spec %+v", spec) - } - if err := cntr.Update(ctx, func(ctx gocontext.Context, client *containerd.Client, c *containers.Container) error { - c.Spec = any - return nil - }); err != nil { - return errors.Wrap(err, "failed to update container spec") - } - return nil -} - -// updateOCILinuxResource updates container resource limit. -func updateOCILinuxResource(ctx context.Context, spec *runtimespec.Spec, new *runtime.LinuxContainerResources, - tolerateMissingHugetlbController, disableHugetlbController bool) (*runtimespec.Spec, error) { - // Copy to make sure old spec is not changed. - var cloned runtimespec.Spec - if err := util.DeepCopy(&cloned, spec); err != nil { - return nil, errors.Wrap(err, "failed to deep copy") - } - if cloned.Linux == nil { - cloned.Linux = &runtimespec.Linux{} - } - if err := opts.WithResources(new, tolerateMissingHugetlbController, disableHugetlbController)(ctx, nil, nil, &cloned); err != nil { - return nil, errors.Wrap(err, "unable to set linux container resources") - } - return &cloned, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_update_resources_windows.go b/vendor/github.com/containerd/cri/pkg/server/container_update_resources_windows.go deleted file mode 100644 index 72d0d459e..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/container_update_resources_windows.go +++ /dev/null @@ -1,31 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/containerd/containerd/errdefs" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// UpdateContainerResources updates ContainerConfig of the container. -// TODO(windows): Figure out whether windows support this. -func (c *criService) UpdateContainerResources(ctx context.Context, r *runtime.UpdateContainerResourcesRequest) (*runtime.UpdateContainerResourcesResponse, error) { - return nil, errdefs.ErrNotImplemented -} diff --git a/vendor/github.com/containerd/cri/pkg/server/events.go b/vendor/github.com/containerd/cri/pkg/server/events.go deleted file mode 100644 index 8f35bf0bd..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/events.go +++ /dev/null @@ -1,461 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "sync" - "time" - - "github.com/containerd/containerd" - eventtypes "github.com/containerd/containerd/api/events" - containerdio "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/events" - "github.com/containerd/typeurl" - gogotypes "github.com/gogo/protobuf/types" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "k8s.io/apimachinery/pkg/util/clock" - - "github.com/containerd/cri/pkg/constants" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -const ( - backOffInitDuration = 1 * time.Second - backOffMaxDuration = 5 * time.Minute - backOffExpireCheckDuration = 1 * time.Second - - // handleEventTimeout is the timeout for handling 1 event. Event monitor - // handles events in serial, if one event blocks the event monitor, no - // other events can be handled. - // Add a timeout for each event handling, events that timeout will be requeued and - // handled again in the future. - handleEventTimeout = 10 * time.Second - - exitChannelSize = 1024 -) - -// eventMonitor monitors containerd event and updates internal state correspondingly. -// TODO(random-liu): Handle event for each container in a separate goroutine. -type eventMonitor struct { - c *criService - ch <-chan *events.Envelope - // exitCh receives container/sandbox exit events from exit monitors. - exitCh chan *eventtypes.TaskExit - errCh <-chan error - ctx context.Context - cancel context.CancelFunc - backOff *backOff -} - -type backOff struct { - queuePool map[string]*backOffQueue - // tickerMu is mutex used to protect the ticker. - tickerMu sync.Mutex - ticker *time.Ticker - minDuration time.Duration - maxDuration time.Duration - checkDuration time.Duration - clock clock.Clock -} - -type backOffQueue struct { - events []interface{} - expireTime time.Time - duration time.Duration - clock clock.Clock -} - -// Create new event monitor. New event monitor will start subscribing containerd event. All events -// happen after it should be monitored. -func newEventMonitor(c *criService) *eventMonitor { - ctx, cancel := context.WithCancel(context.Background()) - return &eventMonitor{ - c: c, - ctx: ctx, - cancel: cancel, - exitCh: make(chan *eventtypes.TaskExit, exitChannelSize), - backOff: newBackOff(), - } -} - -// subscribe starts to subscribe containerd events. -func (em *eventMonitor) subscribe(subscriber events.Subscriber) { - // note: filters are any match, if you want any match but not in namespace foo - // then you have to manually filter namespace foo - filters := []string{ - `topic=="/tasks/oom"`, - `topic~="/images/"`, - } - em.ch, em.errCh = subscriber.Subscribe(em.ctx, filters...) -} - -// startExitMonitor starts an exit monitor for a given container/sandbox. -func (em *eventMonitor) startExitMonitor(ctx context.Context, id string, pid uint32, exitCh <-chan containerd.ExitStatus) <-chan struct{} { - stopCh := make(chan struct{}) - go func() { - defer close(stopCh) - select { - case exitRes := <-exitCh: - exitStatus, exitedAt, err := exitRes.Result() - if err != nil { - logrus.WithError(err).Errorf("Failed to get task exit status for %q", id) - exitStatus = unknownExitCode - exitedAt = time.Now() - } - em.exitCh <- &eventtypes.TaskExit{ - ContainerID: id, - ID: id, - Pid: pid, - ExitStatus: exitStatus, - ExitedAt: exitedAt, - } - case <-ctx.Done(): - } - }() - return stopCh -} - -func convertEvent(e *gogotypes.Any) (string, interface{}, error) { - id := "" - evt, err := typeurl.UnmarshalAny(e) - if err != nil { - return "", nil, errors.Wrap(err, "failed to unmarshalany") - } - - switch e := evt.(type) { - case *eventtypes.TaskOOM: - id = e.ContainerID - case *eventtypes.ImageCreate: - id = e.Name - case *eventtypes.ImageUpdate: - id = e.Name - case *eventtypes.ImageDelete: - id = e.Name - default: - return "", nil, errors.New("unsupported event") - } - return id, evt, nil -} - -// start starts the event monitor which monitors and handles all subscribed events. It returns -// an error channel for the caller to wait for stop errors from the event monitor. -// start must be called after subscribe. -func (em *eventMonitor) start() <-chan error { - errCh := make(chan error) - if em.ch == nil || em.errCh == nil { - panic("event channel is nil") - } - backOffCheckCh := em.backOff.start() - go func() { - defer close(errCh) - for { - select { - case e := <-em.exitCh: - logrus.Debugf("Received exit event %+v", e) - id := e.ID - if em.backOff.isInBackOff(id) { - logrus.Infof("Events for %q is in backoff, enqueue event %+v", id, e) - em.backOff.enBackOff(id, e) - break - } - if err := em.handleEvent(e); err != nil { - logrus.WithError(err).Errorf("Failed to handle exit event %+v for %s", e, id) - em.backOff.enBackOff(id, e) - } - case e := <-em.ch: - logrus.Debugf("Received containerd event timestamp - %v, namespace - %q, topic - %q", e.Timestamp, e.Namespace, e.Topic) - if e.Namespace != constants.K8sContainerdNamespace { - logrus.Debugf("Ignoring events in namespace - %q", e.Namespace) - break - } - id, evt, err := convertEvent(e.Event) - if err != nil { - logrus.WithError(err).Errorf("Failed to convert event %+v", e) - break - } - if em.backOff.isInBackOff(id) { - logrus.Infof("Events for %q is in backoff, enqueue event %+v", id, evt) - em.backOff.enBackOff(id, evt) - break - } - if err := em.handleEvent(evt); err != nil { - logrus.WithError(err).Errorf("Failed to handle event %+v for %s", evt, id) - em.backOff.enBackOff(id, evt) - } - case err := <-em.errCh: - // Close errCh in defer directly if there is no error. - if err != nil { - logrus.WithError(err).Errorf("Failed to handle event stream") - errCh <- err - } - return - case <-backOffCheckCh: - ids := em.backOff.getExpiredIDs() - for _, id := range ids { - queue := em.backOff.deBackOff(id) - for i, any := range queue.events { - if err := em.handleEvent(any); err != nil { - logrus.WithError(err).Errorf("Failed to handle backOff event %+v for %s", any, id) - em.backOff.reBackOff(id, queue.events[i:], queue.duration) - break - } - } - } - } - } - }() - return errCh -} - -// stop stops the event monitor. It will close the event channel. -// Once event monitor is stopped, it can't be started. -func (em *eventMonitor) stop() { - em.backOff.stop() - em.cancel() -} - -// handleEvent handles a containerd event. -func (em *eventMonitor) handleEvent(any interface{}) error { - ctx := ctrdutil.NamespacedContext() - ctx, cancel := context.WithTimeout(ctx, handleEventTimeout) - defer cancel() - - switch e := any.(type) { - case *eventtypes.TaskExit: - logrus.Infof("TaskExit event %+v", e) - // Use ID instead of ContainerID to rule out TaskExit event for exec. - cntr, err := em.c.containerStore.Get(e.ID) - if err == nil { - if err := handleContainerExit(ctx, e, cntr); err != nil { - return errors.Wrap(err, "failed to handle container TaskExit event") - } - return nil - } else if err != store.ErrNotExist { - return errors.Wrap(err, "can't find container for TaskExit event") - } - sb, err := em.c.sandboxStore.Get(e.ID) - if err == nil { - if err := handleSandboxExit(ctx, e, sb); err != nil { - return errors.Wrap(err, "failed to handle sandbox TaskExit event") - } - return nil - } else if err != store.ErrNotExist { - return errors.Wrap(err, "can't find sandbox for TaskExit event") - } - return nil - case *eventtypes.TaskOOM: - logrus.Infof("TaskOOM event %+v", e) - // For TaskOOM, we only care which container it belongs to. - cntr, err := em.c.containerStore.Get(e.ContainerID) - if err != nil { - if err != store.ErrNotExist { - return errors.Wrap(err, "can't find container for TaskOOM event") - } - return nil - } - err = cntr.Status.UpdateSync(func(status containerstore.Status) (containerstore.Status, error) { - status.Reason = oomExitReason - return status, nil - }) - if err != nil { - return errors.Wrap(err, "failed to update container status for TaskOOM event") - } - case *eventtypes.ImageCreate: - logrus.Infof("ImageCreate event %+v", e) - return em.c.updateImage(ctx, e.Name) - case *eventtypes.ImageUpdate: - logrus.Infof("ImageUpdate event %+v", e) - return em.c.updateImage(ctx, e.Name) - case *eventtypes.ImageDelete: - logrus.Infof("ImageDelete event %+v", e) - return em.c.updateImage(ctx, e.Name) - } - - return nil -} - -// handleContainerExit handles TaskExit event for container. -func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr containerstore.Container) error { - // Attach container IO so that `Delete` could cleanup the stream properly. - task, err := cntr.Container.Task(ctx, - func(*containerdio.FIFOSet) (containerdio.IO, error) { - // We can't directly return cntr.IO here, because - // even if cntr.IO is nil, the cio.IO interface - // is not. - // See https://tour.golang.org/methods/12: - // Note that an interface value that holds a nil - // concrete value is itself non-nil. - if cntr.IO != nil { - return cntr.IO, nil - } - return nil, nil - }, - ) - if err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrapf(err, "failed to load task for container") - } - } else { - // TODO(random-liu): [P1] This may block the loop, we may want to spawn a worker - if _, err = task.Delete(ctx, WithNRISandboxDelete(cntr.SandboxID), containerd.WithProcessKill); err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to stop container") - } - // Move on to make sure container status is updated. - } - } - err = cntr.Status.UpdateSync(func(status containerstore.Status) (containerstore.Status, error) { - // If FinishedAt has been set (e.g. with start failure), keep as - // it is. - if status.FinishedAt != 0 { - return status, nil - } - status.Pid = 0 - status.FinishedAt = e.ExitedAt.UnixNano() - status.ExitCode = int32(e.ExitStatus) - // Unknown state can only transit to EXITED state, so we need - // to handle unknown state here. - if status.Unknown { - logrus.Debugf("Container %q transited from UNKNOWN to EXITED", cntr.ID) - status.Unknown = false - } - return status, nil - }) - if err != nil { - return errors.Wrap(err, "failed to update container state") - } - // Using channel to propagate the information of container stop - cntr.Stop() - return nil -} - -// handleSandboxExit handles TaskExit event for sandbox. -func handleSandboxExit(ctx context.Context, e *eventtypes.TaskExit, sb sandboxstore.Sandbox) error { - // No stream attached to sandbox container. - task, err := sb.Container.Task(ctx, nil) - if err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to load task for sandbox") - } - } else { - // TODO(random-liu): [P1] This may block the loop, we may want to spawn a worker - if _, err = task.Delete(ctx, WithNRISandboxDelete(sb.ID), containerd.WithProcessKill); err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to stop sandbox") - } - // Move on to make sure container status is updated. - } - } - err = sb.Status.Update(func(status sandboxstore.Status) (sandboxstore.Status, error) { - status.State = sandboxstore.StateNotReady - status.Pid = 0 - return status, nil - }) - if err != nil { - return errors.Wrap(err, "failed to update sandbox state") - } - // Using channel to propagate the information of sandbox stop - sb.Stop() - return nil -} - -func newBackOff() *backOff { - return &backOff{ - queuePool: map[string]*backOffQueue{}, - minDuration: backOffInitDuration, - maxDuration: backOffMaxDuration, - checkDuration: backOffExpireCheckDuration, - clock: clock.RealClock{}, - } -} - -func (b *backOff) getExpiredIDs() []string { - var ids []string - for id, q := range b.queuePool { - if q.isExpire() { - ids = append(ids, id) - } - } - return ids -} - -func (b *backOff) isInBackOff(key string) bool { - if _, ok := b.queuePool[key]; ok { - return true - } - return false -} - -// enBackOff start to backOff and put event to the tail of queue -func (b *backOff) enBackOff(key string, evt interface{}) { - if queue, ok := b.queuePool[key]; ok { - queue.events = append(queue.events, evt) - return - } - b.queuePool[key] = newBackOffQueue([]interface{}{evt}, b.minDuration, b.clock) -} - -// enBackOff get out the whole queue -func (b *backOff) deBackOff(key string) *backOffQueue { - queue := b.queuePool[key] - delete(b.queuePool, key) - return queue -} - -// enBackOff start to backOff again and put events to the queue -func (b *backOff) reBackOff(key string, events []interface{}, oldDuration time.Duration) { - duration := 2 * oldDuration - if duration > b.maxDuration { - duration = b.maxDuration - } - b.queuePool[key] = newBackOffQueue(events, duration, b.clock) -} - -func (b *backOff) start() <-chan time.Time { - b.tickerMu.Lock() - defer b.tickerMu.Unlock() - b.ticker = time.NewTicker(b.checkDuration) - return b.ticker.C -} - -func (b *backOff) stop() { - b.tickerMu.Lock() - defer b.tickerMu.Unlock() - if b.ticker != nil { - b.ticker.Stop() - } -} - -func newBackOffQueue(events []interface{}, init time.Duration, c clock.Clock) *backOffQueue { - return &backOffQueue{ - events: events, - duration: init, - expireTime: c.Now().Add(init), - clock: c, - } -} - -func (q *backOffQueue) isExpire() bool { - // return time.Now >= expireTime - return !q.clock.Now().Before(q.expireTime) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/helpers.go b/vendor/github.com/containerd/cri/pkg/server/helpers.go deleted file mode 100644 index 34da9a254..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/helpers.go +++ /dev/null @@ -1,390 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "fmt" - "path" - "path/filepath" - "strconv" - "strings" - - "github.com/BurntSushi/toml" - runhcsoptions "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/reference/docker" - "github.com/containerd/containerd/runtime/linux/runctypes" - runcoptions "github.com/containerd/containerd/runtime/v2/runc/options" - "github.com/containerd/typeurl" - imagedigest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - runtimeoptions "github.com/containerd/cri/pkg/api/runtimeoptions/v1" - criconfig "github.com/containerd/cri/pkg/config" - "github.com/containerd/cri/pkg/store" - containerstore "github.com/containerd/cri/pkg/store/container" - imagestore "github.com/containerd/cri/pkg/store/image" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -const ( - // errorStartReason is the exit reason when fails to start container. - errorStartReason = "StartError" - // errorStartExitCode is the exit code when fails to start container. - // 128 is the same with Docker's behavior. - // TODO(windows): Figure out what should be used for windows. - errorStartExitCode = 128 - // completeExitReason is the exit reason when container exits with code 0. - completeExitReason = "Completed" - // errorExitReason is the exit reason when container exits with code non-zero. - errorExitReason = "Error" - // oomExitReason is the exit reason when process in container is oom killed. - oomExitReason = "OOMKilled" - - // sandboxesDir contains all sandbox root. A sandbox root is the running - // directory of the sandbox, all files created for the sandbox will be - // placed under this directory. - sandboxesDir = "sandboxes" - // containersDir contains all container root. - containersDir = "containers" - // Delimiter used to construct container/sandbox names. - nameDelimiter = "_" - - // criContainerdPrefix is common prefix for cri-containerd - criContainerdPrefix = "io.cri-containerd" - // containerKindLabel is a label key indicating container is sandbox container or application container - containerKindLabel = criContainerdPrefix + ".kind" - // containerKindSandbox is a label value indicating container is sandbox container - containerKindSandbox = "sandbox" - // containerKindContainer is a label value indicating container is application container - containerKindContainer = "container" - // imageLabelKey is the label key indicating the image is managed by cri plugin. - imageLabelKey = criContainerdPrefix + ".image" - // imageLabelValue is the label value indicating the image is managed by cri plugin. - imageLabelValue = "managed" - // sandboxMetadataExtension is an extension name that identify metadata of sandbox in CreateContainerRequest - sandboxMetadataExtension = criContainerdPrefix + ".sandbox.metadata" - // containerMetadataExtension is an extension name that identify metadata of container in CreateContainerRequest - containerMetadataExtension = criContainerdPrefix + ".container.metadata" - - // defaultIfName is the default network interface for the pods - defaultIfName = "eth0" - - // runtimeRunhcsV1 is the runtime type for runhcs. - runtimeRunhcsV1 = "io.containerd.runhcs.v1" -) - -// makeSandboxName generates sandbox name from sandbox metadata. The name -// generated is unique as long as sandbox metadata is unique. -func makeSandboxName(s *runtime.PodSandboxMetadata) string { - return strings.Join([]string{ - s.Name, // 0 - s.Namespace, // 1 - s.Uid, // 2 - fmt.Sprintf("%d", s.Attempt), // 3 - }, nameDelimiter) -} - -// makeContainerName generates container name from sandbox and container metadata. -// The name generated is unique as long as the sandbox container combination is -// unique. -func makeContainerName(c *runtime.ContainerMetadata, s *runtime.PodSandboxMetadata) string { - return strings.Join([]string{ - c.Name, // 0 - s.Name, // 1: pod name - s.Namespace, // 2: pod namespace - s.Uid, // 3: pod uid - fmt.Sprintf("%d", c.Attempt), // 4 - }, nameDelimiter) -} - -// getSandboxRootDir returns the root directory for managing sandbox files, -// e.g. hosts files. -func (c *criService) getSandboxRootDir(id string) string { - return filepath.Join(c.config.RootDir, sandboxesDir, id) -} - -// getVolatileSandboxRootDir returns the root directory for managing volatile sandbox files, -// e.g. named pipes. -func (c *criService) getVolatileSandboxRootDir(id string) string { - return filepath.Join(c.config.StateDir, sandboxesDir, id) -} - -// getContainerRootDir returns the root directory for managing container files, -// e.g. state checkpoint. -func (c *criService) getContainerRootDir(id string) string { - return filepath.Join(c.config.RootDir, containersDir, id) -} - -// getVolatileContainerRootDir returns the root directory for managing volatile container files, -// e.g. named pipes. -func (c *criService) getVolatileContainerRootDir(id string) string { - return filepath.Join(c.config.StateDir, containersDir, id) -} - -// criContainerStateToString formats CRI container state to string. -func criContainerStateToString(state runtime.ContainerState) string { - return runtime.ContainerState_name[int32(state)] -} - -// getRepoDigestAngTag returns image repoDigest and repoTag of the named image reference. -func getRepoDigestAndTag(namedRef docker.Named, digest imagedigest.Digest, schema1 bool) (string, string) { - var repoTag, repoDigest string - if _, ok := namedRef.(docker.NamedTagged); ok { - repoTag = namedRef.String() - } - if _, ok := namedRef.(docker.Canonical); ok { - repoDigest = namedRef.String() - } else if !schema1 { - // digest is not actual repo digest for schema1 image. - repoDigest = namedRef.Name() + "@" + digest.String() - } - return repoDigest, repoTag -} - -// localResolve resolves image reference locally and returns corresponding image metadata. It -// returns store.ErrNotExist if the reference doesn't exist. -func (c *criService) localResolve(refOrID string) (imagestore.Image, error) { - getImageID := func(refOrId string) string { - if _, err := imagedigest.Parse(refOrID); err == nil { - return refOrID - } - return func(ref string) string { - // ref is not image id, try to resolve it locally. - // TODO(random-liu): Handle this error better for debugging. - normalized, err := docker.ParseDockerRef(ref) - if err != nil { - return "" - } - id, err := c.imageStore.Resolve(normalized.String()) - if err != nil { - return "" - } - return id - }(refOrID) - } - - imageID := getImageID(refOrID) - if imageID == "" { - // Try to treat ref as imageID - imageID = refOrID - } - return c.imageStore.Get(imageID) -} - -// toContainerdImage converts an image object in image store to containerd image handler. -func (c *criService) toContainerdImage(ctx context.Context, image imagestore.Image) (containerd.Image, error) { - // image should always have at least one reference. - if len(image.References) == 0 { - return nil, errors.Errorf("invalid image with no reference %q", image.ID) - } - return c.client.GetImage(ctx, image.References[0]) -} - -// getUserFromImage gets uid or user name of the image user. -// If user is numeric, it will be treated as uid; or else, it is treated as user name. -func getUserFromImage(user string) (*int64, string) { - // return both empty if user is not specified in the image. - if user == "" { - return nil, "" - } - // split instances where the id may contain user:group - user = strings.Split(user, ":")[0] - // user could be either uid or user name. Try to interpret as numeric uid. - uid, err := strconv.ParseInt(user, 10, 64) - if err != nil { - // If user is non numeric, assume it's user name. - return nil, user - } - // If user is a numeric uid. - return &uid, "" -} - -// ensureImageExists returns corresponding metadata of the image reference, if image is not -// pulled yet, the function will pull the image. -func (c *criService) ensureImageExists(ctx context.Context, ref string, config *runtime.PodSandboxConfig) (*imagestore.Image, error) { - image, err := c.localResolve(ref) - if err != nil && err != store.ErrNotExist { - return nil, errors.Wrapf(err, "failed to get image %q", ref) - } - if err == nil { - return &image, nil - } - // Pull image to ensure the image exists - resp, err := c.PullImage(ctx, &runtime.PullImageRequest{Image: &runtime.ImageSpec{Image: ref}, SandboxConfig: config}) - if err != nil { - return nil, errors.Wrapf(err, "failed to pull image %q", ref) - } - imageID := resp.GetImageRef() - newImage, err := c.imageStore.Get(imageID) - if err != nil { - // It's still possible that someone removed the image right after it is pulled. - return nil, errors.Wrapf(err, "failed to get image %q after pulling", imageID) - } - return &newImage, nil -} - -// isInCRIMounts checks whether a destination is in CRI mount list. -func isInCRIMounts(dst string, mounts []*runtime.Mount) bool { - for _, m := range mounts { - if filepath.Clean(m.ContainerPath) == filepath.Clean(dst) { - return true - } - } - return false -} - -// filterLabel returns a label filter. Use `%q` here because containerd -// filter needs extra quote to work properly. -func filterLabel(k, v string) string { - return fmt.Sprintf("labels.%q==%q", k, v) -} - -// buildLabel builds the labels from config to be passed to containerd -func buildLabels(configLabels map[string]string, containerType string) map[string]string { - labels := make(map[string]string) - for k, v := range configLabels { - labels[k] = v - } - labels[containerKindLabel] = containerType - return labels -} - -// toRuntimeAuthConfig converts cri plugin auth config to runtime auth config. -func toRuntimeAuthConfig(a criconfig.AuthConfig) *runtime.AuthConfig { - return &runtime.AuthConfig{ - Username: a.Username, - Password: a.Password, - Auth: a.Auth, - IdentityToken: a.IdentityToken, - } -} - -// parseImageReferences parses a list of arbitrary image references and returns -// the repotags and repodigests -func parseImageReferences(refs []string) ([]string, []string) { - var tags, digests []string - for _, ref := range refs { - parsed, err := docker.ParseAnyReference(ref) - if err != nil { - continue - } - if _, ok := parsed.(docker.Canonical); ok { - digests = append(digests, parsed.String()) - } else if _, ok := parsed.(docker.Tagged); ok { - tags = append(tags, parsed.String()) - } - } - return tags, digests -} - -// generateRuntimeOptions generates runtime options from cri plugin config. -func generateRuntimeOptions(r criconfig.Runtime, c criconfig.Config) (interface{}, error) { - if r.Options == nil { - if r.Type != plugin.RuntimeLinuxV1 { - return nil, nil - } - // This is a legacy config, generate runctypes.RuncOptions. - return &runctypes.RuncOptions{ - Runtime: r.Engine, - RuntimeRoot: r.Root, - SystemdCgroup: c.SystemdCgroup, - }, nil - } - options := getRuntimeOptionsType(r.Type) - if err := toml.PrimitiveDecode(*r.Options, options); err != nil { - return nil, err - } - return options, nil -} - -// getRuntimeOptionsType gets empty runtime options by the runtime type name. -func getRuntimeOptionsType(t string) interface{} { - switch t { - case plugin.RuntimeRuncV1: - fallthrough - case plugin.RuntimeRuncV2: - return &runcoptions.Options{} - case plugin.RuntimeLinuxV1: - return &runctypes.RuncOptions{} - case runtimeRunhcsV1: - return &runhcsoptions.Options{} - default: - return &runtimeoptions.Options{} - } -} - -// getRuntimeOptions get runtime options from container metadata. -func getRuntimeOptions(c containers.Container) (interface{}, error) { - if c.Runtime.Options == nil { - return nil, nil - } - opts, err := typeurl.UnmarshalAny(c.Runtime.Options) - if err != nil { - return nil, err - } - return opts, nil -} - -const ( - // unknownExitCode is the exit code when exit reason is unknown. - unknownExitCode = 255 - // unknownExitReason is the exit reason when exit reason is unknown. - unknownExitReason = "Unknown" -) - -// unknownContainerStatus returns the default container status when its status is unknown. -func unknownContainerStatus() containerstore.Status { - return containerstore.Status{ - CreatedAt: 0, - StartedAt: 0, - FinishedAt: 0, - ExitCode: unknownExitCode, - Reason: unknownExitReason, - Unknown: true, - } -} - -// unknownSandboxStatus returns the default sandbox status when its status is unknown. -func unknownSandboxStatus() sandboxstore.Status { - return sandboxstore.Status{ - State: sandboxstore.StateUnknown, - } -} - -// getPassthroughAnnotations filters requested pod annotations by comparing -// against permitted annotations for the given runtime. -func getPassthroughAnnotations(podAnnotations map[string]string, - runtimePodAnnotations []string) (passthroughAnnotations map[string]string) { - passthroughAnnotations = make(map[string]string) - - for podAnnotationKey, podAnnotationValue := range podAnnotations { - for _, pattern := range runtimePodAnnotations { - // Use path.Match instead of filepath.Match here. - // filepath.Match treated `\\` as path separator - // on windows, which is not what we want. - if ok, _ := path.Match(pattern, podAnnotationKey); ok { - passthroughAnnotations[podAnnotationKey] = podAnnotationValue - } - } - } - return passthroughAnnotations -} diff --git a/vendor/github.com/containerd/cri/pkg/server/helpers_unix.go b/vendor/github.com/containerd/cri/pkg/server/helpers_unix.go deleted file mode 100644 index 0c3a6652d..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/helpers_unix.go +++ /dev/null @@ -1,292 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "context" - "fmt" - "os" - "path" - "path/filepath" - "regexp" - "sort" - "strings" - "syscall" - "time" - - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/mount" - "github.com/containerd/cri/pkg/seccomp" - "github.com/containerd/cri/pkg/seutil" - runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor" - "github.com/opencontainers/runtime-spec/specs-go" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "golang.org/x/sys/unix" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -const ( - // defaultSandboxOOMAdj is default omm adj for sandbox container. (kubernetes#47938). - defaultSandboxOOMAdj = -998 - // defaultShmSize is the default size of the sandbox shm. - defaultShmSize = int64(1024 * 1024 * 64) - // relativeRootfsPath is the rootfs path relative to bundle path. - relativeRootfsPath = "rootfs" - // According to http://man7.org/linux/man-pages/man5/resolv.conf.5.html: - // "The search list is currently limited to six domains with a total of 256 characters." - maxDNSSearches = 6 - // devShm is the default path of /dev/shm. - devShm = "/dev/shm" - // etcHosts is the default path of /etc/hosts file. - etcHosts = "/etc/hosts" - // etcHostname is the default path of /etc/hostname file. - etcHostname = "/etc/hostname" - // resolvConfPath is the abs path of resolv.conf on host or container. - resolvConfPath = "/etc/resolv.conf" - // hostnameEnv is the key for HOSTNAME env. - hostnameEnv = "HOSTNAME" -) - -// getCgroupsPath generates container cgroups path. -func getCgroupsPath(cgroupsParent, id string) string { - base := path.Base(cgroupsParent) - if strings.HasSuffix(base, ".slice") { - // For a.slice/b.slice/c.slice, base is c.slice. - // runc systemd cgroup path format is "slice:prefix:name". - return strings.Join([]string{base, "cri-containerd", id}, ":") - } - return filepath.Join(cgroupsParent, id) -} - -// getSandboxHostname returns the hostname file path inside the sandbox root directory. -func (c *criService) getSandboxHostname(id string) string { - return filepath.Join(c.getSandboxRootDir(id), "hostname") -} - -// getSandboxHosts returns the hosts file path inside the sandbox root directory. -func (c *criService) getSandboxHosts(id string) string { - return filepath.Join(c.getSandboxRootDir(id), "hosts") -} - -// getResolvPath returns resolv.conf filepath for specified sandbox. -func (c *criService) getResolvPath(id string) string { - return filepath.Join(c.getSandboxRootDir(id), "resolv.conf") -} - -// getSandboxDevShm returns the shm file path inside the sandbox root directory. -func (c *criService) getSandboxDevShm(id string) string { - return filepath.Join(c.getVolatileSandboxRootDir(id), "shm") -} - -func toLabel(selinuxOptions *runtime.SELinuxOption) ([]string, error) { - var labels []string - - if selinuxOptions == nil { - return nil, nil - } - if err := checkSelinuxLevel(selinuxOptions.Level); err != nil { - return nil, err - } - if selinuxOptions.User != "" { - labels = append(labels, "user:"+selinuxOptions.User) - } - if selinuxOptions.Role != "" { - labels = append(labels, "role:"+selinuxOptions.Role) - } - if selinuxOptions.Type != "" { - labels = append(labels, "type:"+selinuxOptions.Type) - } - if selinuxOptions.Level != "" { - labels = append(labels, "level:"+selinuxOptions.Level) - } - - return labels, nil -} - -func initLabelsFromOpt(selinuxOpts *runtime.SELinuxOption) (string, string, error) { - labels, err := toLabel(selinuxOpts) - if err != nil { - return "", "", err - } - return label.InitLabels(labels) -} - -func checkSelinuxLevel(level string) error { - if len(level) == 0 { - return nil - } - - matched, err := regexp.MatchString(`^s\d(-s\d)??(:c\d{1,4}(\.c\d{1,4})?(,c\d{1,4}(\.c\d{1,4})?)*)?$`, level) - if err != nil { - return errors.Wrapf(err, "the format of 'level' %q is not correct", level) - } - if !matched { - return fmt.Errorf("the format of 'level' %q is not correct", level) - } - return nil -} - -func (c *criService) apparmorEnabled() bool { - return runcapparmor.IsEnabled() && !c.config.DisableApparmor -} - -func (c *criService) seccompEnabled() bool { - return seccomp.IsEnabled() -} - -// openLogFile opens/creates a container log file. -func openLogFile(path string) (*os.File, error) { - return os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0640) -} - -// unmountRecursive unmounts the target and all mounts underneath, starting with -// the deepest mount first. -func unmountRecursive(ctx context.Context, target string) error { - mounts, err := mount.Self() - if err != nil { - return err - } - - var toUnmount []string - for _, m := range mounts { - p, err := filepath.Rel(target, m.Mountpoint) - if err != nil { - return err - } - if !strings.HasPrefix(p, "..") { - toUnmount = append(toUnmount, m.Mountpoint) - } - } - - // Make the deepest mount be first - sort.Slice(toUnmount, func(i, j int) bool { - return len(toUnmount[i]) > len(toUnmount[j]) - }) - - for i, mountPath := range toUnmount { - if err := mount.UnmountAll(mountPath, unix.MNT_DETACH); err != nil { - if i == len(toUnmount)-1 { // last mount - return err - } - // This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem - log.G(ctx).WithError(err).Debugf("failed to unmount submount %s", mountPath) - } - } - return nil -} - -// ensureRemoveAll wraps `os.RemoveAll` to check for specific errors that can -// often be remedied. -// Only use `ensureRemoveAll` if you really want to make every effort to remove -// a directory. -// -// Because of the way `os.Remove` (and by extension `os.RemoveAll`) works, there -// can be a race between reading directory entries and then actually attempting -// to remove everything in the directory. -// These types of errors do not need to be returned since it's ok for the dir to -// be gone we can just retry the remove operation. -// -// This should not return a `os.ErrNotExist` kind of error under any circumstances -func ensureRemoveAll(ctx context.Context, dir string) error { - notExistErr := make(map[string]bool) - - // track retries - exitOnErr := make(map[string]int) - maxRetry := 50 - - // Attempt to unmount anything beneath this dir first. - if err := unmountRecursive(ctx, dir); err != nil { - log.G(ctx).WithError(err).Debugf("failed to do initial unmount of %s", dir) - } - - for { - err := os.RemoveAll(dir) - if err == nil { - return nil - } - - pe, ok := err.(*os.PathError) - if !ok { - return err - } - - if os.IsNotExist(err) { - if notExistErr[pe.Path] { - return err - } - notExistErr[pe.Path] = true - - // There is a race where some subdir can be removed but after the - // parent dir entries have been read. - // So the path could be from `os.Remove(subdir)` - // If the reported non-existent path is not the passed in `dir` we - // should just retry, but otherwise return with no error. - if pe.Path == dir { - return nil - } - continue - } - - if pe.Err != syscall.EBUSY { - return err - } - if e := mount.Unmount(pe.Path, unix.MNT_DETACH); e != nil { - return errors.Wrapf(e, "error while removing %s", dir) - } - - if exitOnErr[pe.Path] == maxRetry { - return err - } - exitOnErr[pe.Path]++ - time.Sleep(100 * time.Millisecond) - } -} - -var vmbasedRuntimes = []string{ - "io.containerd.kata", -} - -func isVMBasedRuntime(runtimeType string) bool { - for _, rt := range vmbasedRuntimes { - if strings.Contains(runtimeType, rt) { - return true - } - } - return false -} - -func modifyProcessLabel(runtimeType string, spec *specs.Spec) error { - if !isVMBasedRuntime(runtimeType) { - return nil - } - l, err := getKVMLabel(spec.Process.SelinuxLabel) - if err != nil { - return errors.Wrap(err, "failed to get selinux kvm label") - } - spec.Process.SelinuxLabel = l - return nil -} - -func getKVMLabel(l string) (string, error) { - if !seutil.HasType("container_kvm_t") { - return "", nil - } - return seutil.ChangeToKVM(l) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/helpers_windows.go b/vendor/github.com/containerd/cri/pkg/server/helpers_windows.go deleted file mode 100644 index 5ce7104da..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/helpers_windows.go +++ /dev/null @@ -1,225 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "context" - "os" - "path/filepath" - "syscall" - "time" - - "github.com/opencontainers/runtime-spec/specs-go" -) - -// openLogFile opens/creates a container log file. -// It specifies `FILE_SHARE_DELETE` option to make sure -// log files can be rotated by kubelet. -// TODO(windows): Use golang support after 1.14. (https://github.com/golang/go/issues/32088) -func openLogFile(path string) (*os.File, error) { - path = fixLongPath(path) - if len(path) == 0 { - return nil, syscall.ERROR_FILE_NOT_FOUND - } - pathp, err := syscall.UTF16PtrFromString(path) - if err != nil { - return nil, err - } - createmode := uint32(syscall.OPEN_ALWAYS) - access := uint32(syscall.FILE_APPEND_DATA) - sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE) - h, err := syscall.CreateFile(pathp, access, sharemode, nil, createmode, syscall.FILE_ATTRIBUTE_NORMAL, 0) - if err != nil { - return nil, err - } - return os.NewFile(uintptr(h), path), nil -} - -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// fixLongPath returns the extended-length (\\?\-prefixed) form of -// path when needed, in order to avoid the default 260 character file -// path limit imposed by Windows. If path is not easily converted to -// the extended-length form (for example, if path is a relative path -// or contains .. elements), or is short enough, fixLongPath returns -// path unmodified. -// -// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath -// -// This is copied from https://golang.org/src/path/filepath/path_windows.go. -func fixLongPath(path string) string { - // Do nothing (and don't allocate) if the path is "short". - // Empirically (at least on the Windows Server 2013 builder), - // the kernel is arbitrarily okay with < 248 bytes. That - // matches what the docs above say: - // "When using an API to create a directory, the specified - // path cannot be so long that you cannot append an 8.3 file - // name (that is, the directory name cannot exceed MAX_PATH - // minus 12)." Since MAX_PATH is 260, 260 - 12 = 248. - // - // The MSDN docs appear to say that a normal path that is 248 bytes long - // will work; empirically the path must be less then 248 bytes long. - if len(path) < 248 { - // Don't fix. (This is how Go 1.7 and earlier worked, - // not automatically generating the \\?\ form) - return path - } - - // The extended form begins with \\?\, as in - // \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt. - // The extended form disables evaluation of . and .. path - // elements and disables the interpretation of / as equivalent - // to \. The conversion here rewrites / to \ and elides - // . elements as well as trailing or duplicate separators. For - // simplicity it avoids the conversion entirely for relative - // paths or paths containing .. elements. For now, - // \\server\share paths are not converted to - // \\?\UNC\server\share paths because the rules for doing so - // are less well-specified. - if len(path) >= 2 && path[:2] == `\\` { - // Don't canonicalize UNC paths. - return path - } - if !filepath.IsAbs(path) { - // Relative path - return path - } - - const prefix = `\\?` - - pathbuf := make([]byte, len(prefix)+len(path)+len(`\`)) - copy(pathbuf, prefix) - n := len(path) - r, w := 0, len(prefix) - for r < n { - switch { - case os.IsPathSeparator(path[r]): - // empty block - r++ - case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])): - // /./ - r++ - case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])): - // /../ is currently unhandled - return path - default: - pathbuf[w] = '\\' - w++ - for ; r < n && !os.IsPathSeparator(path[r]); r++ { - pathbuf[w] = path[r] - w++ - } - } - } - // A drive's root directory needs a trailing \ - if w == len(`\\?\c:`) { - pathbuf[w] = '\\' - w++ - } - return string(pathbuf[:w]) -} - -// ensureRemoveAll wraps `os.RemoveAll` to check for specific errors that can -// often be remedied. -// Only use `ensureRemoveAll` if you really want to make every effort to remove -// a directory. -// -// Because of the way `os.Remove` (and by extension `os.RemoveAll`) works, there -// can be a race between reading directory entries and then actually attempting -// to remove everything in the directory. -// These types of errors do not need to be returned since it's ok for the dir to -// be gone we can just retry the remove operation. -// -// This should not return a `os.ErrNotExist` kind of error under any circumstances -func ensureRemoveAll(_ context.Context, dir string) error { - notExistErr := make(map[string]bool) - - // track retries - exitOnErr := make(map[string]int) - maxRetry := 50 - - for { - err := os.RemoveAll(dir) - if err == nil { - return nil - } - - pe, ok := err.(*os.PathError) - if !ok { - return err - } - - if os.IsNotExist(err) { - if notExistErr[pe.Path] { - return err - } - notExistErr[pe.Path] = true - - // There is a race where some subdir can be removed but after the - // parent dir entries have been read. - // So the path could be from `os.Remove(subdir)` - // If the reported non-existent path is not the passed in `dir` we - // should just retry, but otherwise return with no error. - if pe.Path == dir { - return nil - } - continue - } - - if pe.Err != syscall.EBUSY { - return err - } - - if exitOnErr[pe.Path] == maxRetry { - return err - } - exitOnErr[pe.Path]++ - time.Sleep(100 * time.Millisecond) - } -} - -func modifyProcessLabel(runtimeType string, spec *specs.Spec) error { - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/image_list.go b/vendor/github.com/containerd/cri/pkg/server/image_list.go deleted file mode 100644 index dc6aeecc2..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/image_list.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// ListImages lists existing images. -// TODO(random-liu): Add image list filters after CRI defines this more clear, and kubelet -// actually needs it. -func (c *criService) ListImages(ctx context.Context, r *runtime.ListImagesRequest) (*runtime.ListImagesResponse, error) { - imagesInStore := c.imageStore.List() - - var images []*runtime.Image - for _, image := range imagesInStore { - // TODO(random-liu): [P0] Make sure corresponding snapshot exists. What if snapshot - // doesn't exist? - images = append(images, toCRIImage(image)) - } - - return &runtime.ListImagesResponse{Images: images}, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/image_pull.go b/vendor/github.com/containerd/cri/pkg/server/image_pull.go deleted file mode 100644 index 8e2493613..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/image_pull.go +++ /dev/null @@ -1,519 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "crypto/tls" - "crypto/x509" - "encoding/base64" - "fmt" - "io/ioutil" - "net" - "net/http" - "net/url" - "strings" - "time" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" - containerdimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/log" - distribution "github.com/containerd/containerd/reference/docker" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/imgcrypt" - "github.com/containerd/imgcrypt/images/encryption" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - criconfig "github.com/containerd/cri/pkg/config" -) - -// For image management: -// 1) We have an in-memory metadata index to: -// a. Maintain ImageID -> RepoTags, ImageID -> RepoDigset relationships; ImageID -// is the digest of image config, which conforms to oci image spec. -// b. Cache constant and useful information such as image chainID, config etc. -// c. An image will be added into the in-memory metadata only when it's successfully -// pulled and unpacked. -// -// 2) We use containerd image metadata store and content store: -// a. To resolve image reference (digest/tag) locally. During pulling image, we -// normalize the image reference provided by user, and put it into image metadata -// store with resolved descriptor. For the other operations, if image id is provided, -// we'll access the in-memory metadata index directly; if image reference is -// provided, we'll normalize it, resolve it in containerd image metadata store -// to get the image id. -// b. As the backup of in-memory metadata in 1). During startup, the in-memory -// metadata could be re-constructed from image metadata store + content store. -// -// Several problems with current approach: -// 1) An entry in containerd image metadata store doesn't mean a "READY" (successfully -// pulled and unpacked) image. E.g. during pulling, the client gets killed. In that case, -// if we saw an image without snapshots or with in-complete contents during startup, -// should we re-pull the image? Or should we remove the entry? -// -// yanxuean: We can't delete image directly, because we don't know if the image -// is pulled by us. There are resource leakage. -// -// 2) Containerd suggests user to add entry before pulling the image. However if -// an error occurs during the pulling, should we remove the entry from metadata -// store? Or should we leave it there until next startup (resource leakage)? -// -// 3) The cri plugin only exposes "READY" (successfully pulled and unpacked) images -// to the user, which are maintained in the in-memory metadata index. However, it's -// still possible that someone else removes the content or snapshot by-pass the cri plugin, -// how do we detect that and update the in-memory metadata correspondingly? Always -// check whether corresponding snapshot is ready when reporting image status? -// -// 4) Is the content important if we cached necessary information in-memory -// after we pull the image? How to manage the disk usage of contents? If some -// contents are missing but snapshots are ready, is the image still "READY"? - -// PullImage pulls an image with authentication config. -func (c *criService) PullImage(ctx context.Context, r *runtime.PullImageRequest) (*runtime.PullImageResponse, error) { - imageRef := r.GetImage().GetImage() - namedRef, err := distribution.ParseDockerRef(imageRef) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse image reference %q", imageRef) - } - ref := namedRef.String() - if ref != imageRef { - log.G(ctx).Debugf("PullImage using normalized image ref: %q", ref) - } - var ( - resolver = docker.NewResolver(docker.ResolverOptions{ - Headers: c.config.Registry.Headers, - Hosts: c.registryHosts(r.GetAuth()), - }) - isSchema1 bool - imageHandler containerdimages.HandlerFunc = func(_ context.Context, - desc imagespec.Descriptor) ([]imagespec.Descriptor, error) { - if desc.MediaType == containerdimages.MediaTypeDockerSchema1Manifest { - isSchema1 = true - } - return nil, nil - } - ) - - pullOpts := []containerd.RemoteOpt{ - containerd.WithSchema1Conversion, - containerd.WithResolver(resolver), - containerd.WithPullSnapshotter(c.config.ContainerdConfig.Snapshotter), - containerd.WithPullUnpack, - containerd.WithPullLabel(imageLabelKey, imageLabelValue), - containerd.WithMaxConcurrentDownloads(c.config.MaxConcurrentDownloads), - containerd.WithImageHandler(imageHandler), - } - - pullOpts = append(pullOpts, c.encryptedImagesPullOpts()...) - if !c.config.ContainerdConfig.DisableSnapshotAnnotations { - pullOpts = append(pullOpts, - containerd.WithImageHandlerWrapper(appendInfoHandlerWrapper(ref))) - } - - if c.config.ContainerdConfig.DiscardUnpackedLayers { - // Allows GC to clean layers up from the content store after unpacking - pullOpts = append(pullOpts, - containerd.WithChildLabelMap(containerdimages.ChildGCLabelsFilterLayers)) - } - - image, err := c.client.Pull(ctx, ref, pullOpts...) - if err != nil { - return nil, errors.Wrapf(err, "failed to pull and unpack image %q", ref) - } - - configDesc, err := image.Config(ctx) - if err != nil { - return nil, errors.Wrap(err, "get image config descriptor") - } - imageID := configDesc.Digest.String() - - repoDigest, repoTag := getRepoDigestAndTag(namedRef, image.Target().Digest, isSchema1) - for _, r := range []string{imageID, repoTag, repoDigest} { - if r == "" { - continue - } - if err := c.createImageReference(ctx, r, image.Target()); err != nil { - return nil, errors.Wrapf(err, "failed to create image reference %q", r) - } - // Update image store to reflect the newest state in containerd. - // No need to use `updateImage`, because the image reference must - // have been managed by the cri plugin. - if err := c.imageStore.Update(ctx, r); err != nil { - return nil, errors.Wrapf(err, "failed to update image store %q", r) - } - } - - log.G(ctx).Debugf("Pulled image %q with image id %q, repo tag %q, repo digest %q", imageRef, imageID, - repoTag, repoDigest) - // NOTE(random-liu): the actual state in containerd is the source of truth, even we maintain - // in-memory image store, it's only for in-memory indexing. The image could be removed - // by someone else anytime, before/during/after we create the metadata. We should always - // check the actual state in containerd before using the image or returning status of the - // image. - return &runtime.PullImageResponse{ImageRef: imageID}, nil -} - -// ParseAuth parses AuthConfig and returns username and password/secret required by containerd. -func ParseAuth(auth *runtime.AuthConfig, host string) (string, string, error) { - if auth == nil { - return "", "", nil - } - if auth.ServerAddress != "" { - // Do not return the auth info when server address doesn't match. - u, err := url.Parse(auth.ServerAddress) - if err != nil { - return "", "", errors.Wrap(err, "parse server address") - } - if host != u.Host { - return "", "", nil - } - } - if auth.Username != "" { - return auth.Username, auth.Password, nil - } - if auth.IdentityToken != "" { - return "", auth.IdentityToken, nil - } - if auth.Auth != "" { - decLen := base64.StdEncoding.DecodedLen(len(auth.Auth)) - decoded := make([]byte, decLen) - _, err := base64.StdEncoding.Decode(decoded, []byte(auth.Auth)) - if err != nil { - return "", "", err - } - fields := strings.SplitN(string(decoded), ":", 2) - if len(fields) != 2 { - return "", "", errors.Errorf("invalid decoded auth: %q", decoded) - } - user, passwd := fields[0], fields[1] - return user, strings.Trim(passwd, "\x00"), nil - } - // TODO(random-liu): Support RegistryToken. - // An empty auth config is valid for anonymous registry - return "", "", nil -} - -// createImageReference creates image reference inside containerd image store. -// Note that because create and update are not finished in one transaction, there could be race. E.g. -// the image reference is deleted by someone else after create returns already exists, but before update -// happens. -func (c *criService) createImageReference(ctx context.Context, name string, desc imagespec.Descriptor) error { - img := containerdimages.Image{ - Name: name, - Target: desc, - // Add a label to indicate that the image is managed by the cri plugin. - Labels: map[string]string{imageLabelKey: imageLabelValue}, - } - // TODO(random-liu): Figure out which is the more performant sequence create then update or - // update then create. - oldImg, err := c.client.ImageService().Create(ctx, img) - if err == nil || !errdefs.IsAlreadyExists(err) { - return err - } - if oldImg.Target.Digest == img.Target.Digest && oldImg.Labels[imageLabelKey] == imageLabelValue { - return nil - } - _, err = c.client.ImageService().Update(ctx, img, "target", "labels") - return err -} - -// updateImage updates image store to reflect the newest state of an image reference -// in containerd. If the reference is not managed by the cri plugin, the function also -// generates necessary metadata for the image and make it managed. -func (c *criService) updateImage(ctx context.Context, r string) error { - img, err := c.client.GetImage(ctx, r) - if err != nil && !errdefs.IsNotFound(err) { - return errors.Wrap(err, "get image by reference") - } - if err == nil && img.Labels()[imageLabelKey] != imageLabelValue { - // Make sure the image has the image id as its unique - // identifier that references the image in its lifetime. - configDesc, err := img.Config(ctx) - if err != nil { - return errors.Wrap(err, "get image id") - } - id := configDesc.Digest.String() - if err := c.createImageReference(ctx, id, img.Target()); err != nil { - return errors.Wrapf(err, "create image id reference %q", id) - } - if err := c.imageStore.Update(ctx, id); err != nil { - return errors.Wrapf(err, "update image store for %q", id) - } - // The image id is ready, add the label to mark the image as managed. - if err := c.createImageReference(ctx, r, img.Target()); err != nil { - return errors.Wrap(err, "create managed label") - } - } - // If the image is not found, we should continue updating the cache, - // so that the image can be removed from the cache. - if err := c.imageStore.Update(ctx, r); err != nil { - return errors.Wrapf(err, "update image store for %q", r) - } - return nil -} - -// getTLSConfig returns a TLSConfig configured with a CA/Cert/Key specified by registryTLSConfig -func (c *criService) getTLSConfig(registryTLSConfig criconfig.TLSConfig) (*tls.Config, error) { - var ( - tlsConfig = &tls.Config{} - cert tls.Certificate - err error - ) - if registryTLSConfig.CertFile != "" && registryTLSConfig.KeyFile == "" { - return nil, errors.Errorf("cert file %q was specified, but no corresponding key file was specified", registryTLSConfig.CertFile) - } - if registryTLSConfig.CertFile == "" && registryTLSConfig.KeyFile != "" { - return nil, errors.Errorf("key file %q was specified, but no corresponding cert file was specified", registryTLSConfig.KeyFile) - } - if registryTLSConfig.CertFile != "" && registryTLSConfig.KeyFile != "" { - cert, err = tls.LoadX509KeyPair(registryTLSConfig.CertFile, registryTLSConfig.KeyFile) - if err != nil { - return nil, errors.Wrap(err, "failed to load cert file") - } - if len(cert.Certificate) != 0 { - tlsConfig.Certificates = []tls.Certificate{cert} - } - tlsConfig.BuildNameToCertificate() // nolint:staticcheck - } - - if registryTLSConfig.CAFile != "" { - caCertPool, err := x509.SystemCertPool() - if err != nil { - return nil, errors.Wrap(err, "failed to get system cert pool") - } - caCert, err := ioutil.ReadFile(registryTLSConfig.CAFile) - if err != nil { - return nil, errors.Wrap(err, "failed to load CA file") - } - caCertPool.AppendCertsFromPEM(caCert) - tlsConfig.RootCAs = caCertPool - } - - tlsConfig.InsecureSkipVerify = registryTLSConfig.InsecureSkipVerify - return tlsConfig, nil -} - -// registryHosts is the registry hosts to be used by the resolver. -func (c *criService) registryHosts(auth *runtime.AuthConfig) docker.RegistryHosts { - return func(host string) ([]docker.RegistryHost, error) { - var registries []docker.RegistryHost - - endpoints, err := c.registryEndpoints(host) - if err != nil { - return nil, errors.Wrap(err, "get registry endpoints") - } - for _, e := range endpoints { - u, err := url.Parse(e) - if err != nil { - return nil, errors.Wrapf(err, "parse registry endpoint %q from mirrors", e) - } - - var ( - transport = newTransport() - client = &http.Client{Transport: transport} - config = c.config.Registry.Configs[u.Host] - ) - - if config.TLS != nil { - transport.TLSClientConfig, err = c.getTLSConfig(*config.TLS) - if err != nil { - return nil, errors.Wrapf(err, "get TLSConfig for registry %q", e) - } - } - - if auth == nil && config.Auth != nil { - auth = toRuntimeAuthConfig(*config.Auth) - } - - if u.Path == "" { - u.Path = "/v2" - } - - registries = append(registries, docker.RegistryHost{ - Client: client, - Authorizer: docker.NewDockerAuthorizer( - docker.WithAuthClient(client), - docker.WithAuthCreds(func(host string) (string, string, error) { - return ParseAuth(auth, host) - })), - Host: u.Host, - Scheme: u.Scheme, - Path: u.Path, - Capabilities: docker.HostCapabilityResolve | docker.HostCapabilityPull, - }) - } - return registries, nil - } -} - -// defaultScheme returns the default scheme for a registry host. -func defaultScheme(host string) string { - if h, _, err := net.SplitHostPort(host); err == nil { - host = h - } - if host == "localhost" || host == "127.0.0.1" || host == "::1" { - return "http" - } - return "https" -} - -// addDefaultScheme returns the endpoint with default scheme -func addDefaultScheme(endpoint string) (string, error) { - if strings.Contains(endpoint, "://") { - return endpoint, nil - } - ue := "dummy://" + endpoint - u, err := url.Parse(ue) - if err != nil { - return "", err - } - return fmt.Sprintf("%s://%s", defaultScheme(u.Host), endpoint), nil -} - -// registryEndpoints returns endpoints for a given host. -// It adds default registry endpoint if it does not exist in the passed-in endpoint list. -// It also supports wildcard host matching with `*`. -func (c *criService) registryEndpoints(host string) ([]string, error) { - var endpoints []string - _, ok := c.config.Registry.Mirrors[host] - if ok { - endpoints = c.config.Registry.Mirrors[host].Endpoints - } else { - endpoints = c.config.Registry.Mirrors["*"].Endpoints - } - defaultHost, err := docker.DefaultHost(host) - if err != nil { - return nil, errors.Wrap(err, "get default host") - } - for i := range endpoints { - en, err := addDefaultScheme(endpoints[i]) - if err != nil { - return nil, errors.Wrap(err, "parse endpoint url") - } - endpoints[i] = en - } - for _, e := range endpoints { - u, err := url.Parse(e) - if err != nil { - return nil, errors.Wrap(err, "parse endpoint url") - } - if u.Host == host { - // Do not add default if the endpoint already exists. - return endpoints, nil - } - } - return append(endpoints, defaultScheme(defaultHost)+"://"+defaultHost), nil -} - -// newTransport returns a new HTTP transport used to pull image. -// TODO(random-liu): Create a library and share this code with `ctr`. -func newTransport() *http.Transport { - return &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - FallbackDelay: 300 * time.Millisecond, - }).DialContext, - MaxIdleConns: 10, - IdleConnTimeout: 30 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 5 * time.Second, - } -} - -// encryptedImagesPullOpts returns the necessary list of pull options required -// for decryption of encrypted images based on the cri decryption configuration. -func (c *criService) encryptedImagesPullOpts() []containerd.RemoteOpt { - if c.config.ImageDecryption.KeyModel == criconfig.KeyModelNode { - ltdd := imgcrypt.Payload{} - decUnpackOpt := encryption.WithUnpackConfigApplyOpts(encryption.WithDecryptedUnpack(<dd)) - opt := containerd.WithUnpackOpts([]containerd.UnpackOpt{decUnpackOpt}) - return []containerd.RemoteOpt{opt} - } - return nil -} - -const ( - // targetRefLabel is a label which contains image reference and will be passed - // to snapshotters. - targetRefLabel = "containerd.io/snapshot/cri.image-ref" - // targetDigestLabel is a label which contains layer digest and will be passed - // to snapshotters. - targetDigestLabel = "containerd.io/snapshot/cri.layer-digest" - // targetImageLayersLabel is a label which contains layer digests contained in - // the target image and will be passed to snapshotters for preparing layers in - // parallel. Skipping some layers is allowed and only affects performance. - targetImageLayersLabel = "containerd.io/snapshot/cri.image-layers" -) - -// appendInfoHandlerWrapper makes a handler which appends some basic information -// of images to each layer descriptor as annotations during unpack. These -// annotations will be passed to snapshotters as labels. These labels will be -// used mainly by stargz-based snapshotters for querying image contents from the -// registry. -func appendInfoHandlerWrapper(ref string) func(f containerdimages.Handler) containerdimages.Handler { - return func(f containerdimages.Handler) containerdimages.Handler { - return containerdimages.HandlerFunc(func(ctx context.Context, desc imagespec.Descriptor) ([]imagespec.Descriptor, error) { - children, err := f.Handle(ctx, desc) - if err != nil { - return nil, err - } - switch desc.MediaType { - case imagespec.MediaTypeImageManifest, containerdimages.MediaTypeDockerSchema2Manifest: - for i := range children { - c := &children[i] - if containerdimages.IsLayerType(c.MediaType) { - if c.Annotations == nil { - c.Annotations = make(map[string]string) - } - c.Annotations[targetRefLabel] = ref - c.Annotations[targetDigestLabel] = c.Digest.String() - c.Annotations[targetImageLayersLabel] = getLayers(ctx, targetImageLayersLabel, children[i:], labels.Validate) - } - } - } - return children, nil - }) - } -} - -// getLayers returns comma-separated digests based on the passed list of -// descriptors. The returned list contains as many digests as possible as well -// as meets the label validation. -func getLayers(ctx context.Context, key string, descs []imagespec.Descriptor, validate func(k, v string) error) (layers string) { - var item string - for _, l := range descs { - if containerdimages.IsLayerType(l.MediaType) { - item = l.Digest.String() - if layers != "" { - item = "," + item - } - // This avoids the label hits the size limitation. - if err := validate(key, layers+item); err != nil { - log.G(ctx).WithError(err).WithField("label", key).Debugf("%q is omitted in the layers list", l.Digest.String()) - break - } - layers += item - } - } - return -} diff --git a/vendor/github.com/containerd/cri/pkg/server/image_remove.go b/vendor/github.com/containerd/cri/pkg/server/image_remove.go deleted file mode 100644 index bcd02d758..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/image_remove.go +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/store" -) - -// RemoveImage removes the image. -// TODO(random-liu): Update CRI to pass image reference instead of ImageSpec. (See -// kubernetes/kubernetes#46255) -// TODO(random-liu): We should change CRI to distinguish image id and image spec. -// Remove the whole image no matter the it's image id or reference. This is the -// semantic defined in CRI now. -func (c *criService) RemoveImage(ctx context.Context, r *runtime.RemoveImageRequest) (*runtime.RemoveImageResponse, error) { - image, err := c.localResolve(r.GetImage().GetImage()) - if err != nil { - if err == store.ErrNotExist { - // return empty without error when image not found. - return &runtime.RemoveImageResponse{}, nil - } - return nil, errors.Wrapf(err, "can not resolve %q locally", r.GetImage().GetImage()) - } - - // Remove all image references. - for i, ref := range image.References { - var opts []images.DeleteOpt - if i == len(image.References)-1 { - // Delete the last image reference synchronously to trigger garbage collection. - // This is best effort. It is possible that the image reference is deleted by - // someone else before this point. - opts = []images.DeleteOpt{images.SynchronousDelete()} - } - err = c.client.ImageService().Delete(ctx, ref, opts...) - if err == nil || errdefs.IsNotFound(err) { - // Update image store to reflect the newest state in containerd. - if err := c.imageStore.Update(ctx, ref); err != nil { - return nil, errors.Wrapf(err, "failed to update image reference %q for %q", ref, image.ID) - } - continue - } - return nil, errors.Wrapf(err, "failed to delete image reference %q for %q", ref, image.ID) - } - return &runtime.RemoveImageResponse{}, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/image_status.go b/vendor/github.com/containerd/cri/pkg/server/image_status.go deleted file mode 100644 index 5ada7b007..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/image_status.go +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "encoding/json" - - "github.com/containerd/containerd/log" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/store" - imagestore "github.com/containerd/cri/pkg/store/image" -) - -// ImageStatus returns the status of the image, returns nil if the image isn't present. -// TODO(random-liu): We should change CRI to distinguish image id and image spec. (See -// kubernetes/kubernetes#46255) -func (c *criService) ImageStatus(ctx context.Context, r *runtime.ImageStatusRequest) (*runtime.ImageStatusResponse, error) { - image, err := c.localResolve(r.GetImage().GetImage()) - if err != nil { - if err == store.ErrNotExist { - // return empty without error when image not found. - return &runtime.ImageStatusResponse{}, nil - } - return nil, errors.Wrapf(err, "can not resolve %q locally", r.GetImage().GetImage()) - } - // TODO(random-liu): [P0] Make sure corresponding snapshot exists. What if snapshot - // doesn't exist? - - runtimeImage := toCRIImage(image) - info, err := c.toCRIImageInfo(ctx, &image, r.GetVerbose()) - if err != nil { - return nil, errors.Wrap(err, "failed to generate image info") - } - - return &runtime.ImageStatusResponse{ - Image: runtimeImage, - Info: info, - }, nil -} - -// toCRIImage converts internal image object to CRI runtime.Image. -func toCRIImage(image imagestore.Image) *runtime.Image { - repoTags, repoDigests := parseImageReferences(image.References) - runtimeImage := &runtime.Image{ - Id: image.ID, - RepoTags: repoTags, - RepoDigests: repoDigests, - Size_: uint64(image.Size), - } - uid, username := getUserFromImage(image.ImageSpec.Config.User) - if uid != nil { - runtimeImage.Uid = &runtime.Int64Value{Value: *uid} - } - runtimeImage.Username = username - - return runtimeImage -} - -// TODO (mikebrow): discuss moving this struct and / or constants for info map for some or all of these fields to CRI -type verboseImageInfo struct { - ChainID string `json:"chainID"` - ImageSpec imagespec.Image `json:"imageSpec"` -} - -// toCRIImageInfo converts internal image object information to CRI image status response info map. -func (c *criService) toCRIImageInfo(ctx context.Context, image *imagestore.Image, verbose bool) (map[string]string, error) { - if !verbose { - return nil, nil - } - - info := make(map[string]string) - - imi := &verboseImageInfo{ - ChainID: image.ChainID, - ImageSpec: image.ImageSpec, - } - - m, err := json.Marshal(imi) - if err == nil { - info["info"] = string(m) - } else { - log.G(ctx).WithError(err).Errorf("failed to marshal info %v", imi) - info["info"] = err.Error() - } - - return info, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/imagefs_info.go b/vendor/github.com/containerd/cri/pkg/server/imagefs_info.go deleted file mode 100644 index 81dbd5cd0..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/imagefs_info.go +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "time" - - "golang.org/x/net/context" - - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// ImageFsInfo returns information of the filesystem that is used to store images. -// TODO(windows): Usage for windows is always 0 right now. Support this for windows. -func (c *criService) ImageFsInfo(ctx context.Context, r *runtime.ImageFsInfoRequest) (*runtime.ImageFsInfoResponse, error) { - snapshots := c.snapshotStore.List() - timestamp := time.Now().UnixNano() - var usedBytes, inodesUsed uint64 - for _, sn := range snapshots { - // Use the oldest timestamp as the timestamp of imagefs info. - if sn.Timestamp < timestamp { - timestamp = sn.Timestamp - } - usedBytes += sn.Size - inodesUsed += sn.Inodes - } - // TODO(random-liu): Handle content store - return &runtime.ImageFsInfoResponse{ - ImageFilesystems: []*runtime.FilesystemUsage{ - { - Timestamp: timestamp, - FsId: &runtime.FilesystemIdentifier{Mountpoint: c.imageFSPath}, - UsedBytes: &runtime.UInt64Value{Value: usedBytes}, - InodesUsed: &runtime.UInt64Value{Value: inodesUsed}, - }, - }, - }, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/instrumented_service.go b/vendor/github.com/containerd/cri/pkg/server/instrumented_service.go deleted file mode 100644 index 2c2528ab6..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/instrumented_service.go +++ /dev/null @@ -1,490 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "errors" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - ctrdutil "github.com/containerd/cri/pkg/containerd/util" -) - -// instrumentedService wraps service with containerd namespace and logs. -type instrumentedService struct { - c *criService -} - -func newInstrumentedService(c *criService) grpcServices { - return &instrumentedService{c: c} -} - -// checkInitialized returns error if the server is not fully initialized. -// GRPC service request handlers should return error before server is fully -// initialized. -// NOTE(random-liu): All following functions MUST check initialized at the beginning. -func (in *instrumentedService) checkInitialized() error { - if in.c.initialized.IsSet() { - return nil - } - return errors.New("server is not initialized yet") -} - -func (in *instrumentedService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandboxRequest) (res *runtime.RunPodSandboxResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("RunPodsandbox for %+v", r.GetConfig().GetMetadata()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("RunPodSandbox for %+v failed, error", r.GetConfig().GetMetadata()) - } else { - log.G(ctx).Infof("RunPodSandbox for %+v returns sandbox id %q", r.GetConfig().GetMetadata(), res.GetPodSandboxId()) - } - }() - res, err = in.c.RunPodSandbox(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ListPodSandbox(ctx context.Context, r *runtime.ListPodSandboxRequest) (res *runtime.ListPodSandboxResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("ListPodSandbox with filter %+v", r.GetFilter()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Error("ListPodSandbox failed") - } else { - log.G(ctx).Tracef("ListPodSandbox returns pod sandboxes %+v", res.GetItems()) - } - }() - res, err = in.c.ListPodSandbox(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) PodSandboxStatus(ctx context.Context, r *runtime.PodSandboxStatusRequest) (res *runtime.PodSandboxStatusResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("PodSandboxStatus for %q", r.GetPodSandboxId()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("PodSandboxStatus for %q failed", r.GetPodSandboxId()) - } else { - log.G(ctx).Tracef("PodSandboxStatus for %q returns status %+v", r.GetPodSandboxId(), res.GetStatus()) - } - }() - res, err = in.c.PodSandboxStatus(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandboxRequest) (_ *runtime.StopPodSandboxResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("StopPodSandbox for %q", r.GetPodSandboxId()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("StopPodSandbox for %q failed", r.GetPodSandboxId()) - } else { - log.G(ctx).Infof("StopPodSandbox for %q returns successfully", r.GetPodSandboxId()) - } - }() - res, err := in.c.StopPodSandbox(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodSandboxRequest) (_ *runtime.RemovePodSandboxResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("RemovePodSandbox for %q", r.GetPodSandboxId()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("RemovePodSandbox for %q failed", r.GetPodSandboxId()) - } else { - log.G(ctx).Infof("RemovePodSandbox %q returns successfully", r.GetPodSandboxId()) - } - }() - res, err := in.c.RemovePodSandbox(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) PortForward(ctx context.Context, r *runtime.PortForwardRequest) (res *runtime.PortForwardResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("Portforward for %q port %v", r.GetPodSandboxId(), r.GetPort()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("Portforward for %q failed", r.GetPodSandboxId()) - } else { - log.G(ctx).Infof("Portforward for %q returns URL %q", r.GetPodSandboxId(), res.GetUrl()) - } - }() - res, err = in.c.PortForward(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) CreateContainer(ctx context.Context, r *runtime.CreateContainerRequest) (res *runtime.CreateContainerResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("CreateContainer within sandbox %q for container %+v", - r.GetPodSandboxId(), r.GetConfig().GetMetadata()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("CreateContainer within sandbox %q for %+v failed", - r.GetPodSandboxId(), r.GetConfig().GetMetadata()) - } else { - log.G(ctx).Infof("CreateContainer within sandbox %q for %+v returns container id %q", - r.GetPodSandboxId(), r.GetConfig().GetMetadata(), res.GetContainerId()) - } - }() - res, err = in.c.CreateContainer(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) StartContainer(ctx context.Context, r *runtime.StartContainerRequest) (_ *runtime.StartContainerResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("StartContainer for %q", r.GetContainerId()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("StartContainer for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Infof("StartContainer for %q returns successfully", r.GetContainerId()) - } - }() - res, err := in.c.StartContainer(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ListContainers(ctx context.Context, r *runtime.ListContainersRequest) (res *runtime.ListContainersResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("ListContainers with filter %+v", r.GetFilter()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("ListContainers with filter %+v failed", r.GetFilter()) - } else { - log.G(ctx).Tracef("ListContainers with filter %+v returns containers %+v", - r.GetFilter(), res.GetContainers()) - } - }() - res, err = in.c.ListContainers(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ContainerStatus(ctx context.Context, r *runtime.ContainerStatusRequest) (res *runtime.ContainerStatusResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("ContainerStatus for %q", r.GetContainerId()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("ContainerStatus for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Tracef("ContainerStatus for %q returns status %+v", r.GetContainerId(), res.GetStatus()) - } - }() - res, err = in.c.ContainerStatus(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) StopContainer(ctx context.Context, r *runtime.StopContainerRequest) (res *runtime.StopContainerResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("StopContainer for %q with timeout %d (s)", r.GetContainerId(), r.GetTimeout()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("StopContainer for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Infof("StopContainer for %q returns successfully", r.GetContainerId()) - } - }() - res, err = in.c.StopContainer(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) RemoveContainer(ctx context.Context, r *runtime.RemoveContainerRequest) (res *runtime.RemoveContainerResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("RemoveContainer for %q", r.GetContainerId()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("RemoveContainer for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Infof("RemoveContainer for %q returns successfully", r.GetContainerId()) - } - }() - res, err = in.c.RemoveContainer(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ExecSync(ctx context.Context, r *runtime.ExecSyncRequest) (res *runtime.ExecSyncResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("ExecSync for %q with command %+v and timeout %d (s)", r.GetContainerId(), r.GetCmd(), r.GetTimeout()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("ExecSync for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Infof("ExecSync for %q returns with exit code %d", r.GetContainerId(), res.GetExitCode()) - log.G(ctx).Debugf("ExecSync for %q outputs - stdout: %q, stderr: %q", r.GetContainerId(), - res.GetStdout(), res.GetStderr()) - } - }() - res, err = in.c.ExecSync(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) Exec(ctx context.Context, r *runtime.ExecRequest) (res *runtime.ExecResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("Exec for %q with command %+v, tty %v and stdin %v", - r.GetContainerId(), r.GetCmd(), r.GetTty(), r.GetStdin()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("Exec for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Infof("Exec for %q returns URL %q", r.GetContainerId(), res.GetUrl()) - } - }() - res, err = in.c.Exec(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) Attach(ctx context.Context, r *runtime.AttachRequest) (res *runtime.AttachResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("Attach for %q with tty %v and stdin %v", r.GetContainerId(), r.GetTty(), r.GetStdin()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("Attach for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Infof("Attach for %q returns URL %q", r.GetContainerId(), res.Url) - } - }() - res, err = in.c.Attach(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) UpdateContainerResources(ctx context.Context, r *runtime.UpdateContainerResourcesRequest) (res *runtime.UpdateContainerResourcesResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("UpdateContainerResources for %q with %+v", r.GetContainerId(), r.GetLinux()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("UpdateContainerResources for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Infof("UpdateContainerResources for %q returns successfully", r.GetContainerId()) - } - }() - res, err = in.c.UpdateContainerResources(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) PullImage(ctx context.Context, r *runtime.PullImageRequest) (res *runtime.PullImageResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("PullImage %q", r.GetImage().GetImage()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("PullImage %q failed", r.GetImage().GetImage()) - } else { - log.G(ctx).Infof("PullImage %q returns image reference %q", - r.GetImage().GetImage(), res.GetImageRef()) - } - }() - res, err = in.c.PullImage(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ListImages(ctx context.Context, r *runtime.ListImagesRequest) (res *runtime.ListImagesResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("ListImages with filter %+v", r.GetFilter()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("ListImages with filter %+v failed", r.GetFilter()) - } else { - log.G(ctx).Tracef("ListImages with filter %+v returns image list %+v", - r.GetFilter(), res.GetImages()) - } - }() - res, err = in.c.ListImages(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ImageStatus(ctx context.Context, r *runtime.ImageStatusRequest) (res *runtime.ImageStatusResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("ImageStatus for %q", r.GetImage().GetImage()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("ImageStatus for %q failed", r.GetImage().GetImage()) - } else { - log.G(ctx).Tracef("ImageStatus for %q returns image status %+v", - r.GetImage().GetImage(), res.GetImage()) - } - }() - res, err = in.c.ImageStatus(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) RemoveImage(ctx context.Context, r *runtime.RemoveImageRequest) (_ *runtime.RemoveImageResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Infof("RemoveImage %q", r.GetImage().GetImage()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("RemoveImage %q failed", r.GetImage().GetImage()) - } else { - log.G(ctx).Infof("RemoveImage %q returns successfully", r.GetImage().GetImage()) - } - }() - res, err := in.c.RemoveImage(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ImageFsInfo(ctx context.Context, r *runtime.ImageFsInfoRequest) (res *runtime.ImageFsInfoResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Debugf("ImageFsInfo") - defer func() { - if err != nil { - log.G(ctx).WithError(err).Error("ImageFsInfo failed") - } else { - log.G(ctx).Debugf("ImageFsInfo returns filesystem info %+v", res.ImageFilesystems) - } - }() - res, err = in.c.ImageFsInfo(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ContainerStats(ctx context.Context, r *runtime.ContainerStatsRequest) (res *runtime.ContainerStatsResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Debugf("ContainerStats for %q", r.GetContainerId()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("ContainerStats for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Debugf("ContainerStats for %q returns stats %+v", r.GetContainerId(), res.GetStats()) - } - }() - res, err = in.c.ContainerStats(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ListContainerStats(ctx context.Context, r *runtime.ListContainerStatsRequest) (res *runtime.ListContainerStatsResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("ListContainerStats with filter %+v", r.GetFilter()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Error("ListContainerStats failed") - } else { - log.G(ctx).Tracef("ListContainerStats returns stats %+v", res.GetStats()) - } - }() - res, err = in.c.ListContainerStats(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) Status(ctx context.Context, r *runtime.StatusRequest) (res *runtime.StatusResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("Status") - defer func() { - if err != nil { - log.G(ctx).WithError(err).Error("Status failed") - } else { - log.G(ctx).Tracef("Status returns status %+v", res.GetStatus()) - } - }() - res, err = in.c.Status(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) Version(ctx context.Context, r *runtime.VersionRequest) (res *runtime.VersionResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Tracef("Version with client side version %q", r.GetVersion()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Error("Version failed") - } else { - log.G(ctx).Tracef("Version returns %+v", res) - } - }() - res, err = in.c.Version(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) UpdateRuntimeConfig(ctx context.Context, r *runtime.UpdateRuntimeConfigRequest) (res *runtime.UpdateRuntimeConfigResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Debugf("UpdateRuntimeConfig with config %+v", r.GetRuntimeConfig()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Error("UpdateRuntimeConfig failed") - } else { - log.G(ctx).Debug("UpdateRuntimeConfig returns returns successfully") - } - }() - res, err = in.c.UpdateRuntimeConfig(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} - -func (in *instrumentedService) ReopenContainerLog(ctx context.Context, r *runtime.ReopenContainerLogRequest) (res *runtime.ReopenContainerLogResponse, err error) { - if err := in.checkInitialized(); err != nil { - return nil, err - } - log.G(ctx).Debugf("ReopenContainerLog for %q", r.GetContainerId()) - defer func() { - if err != nil { - log.G(ctx).WithError(err).Errorf("ReopenContainerLog for %q failed", r.GetContainerId()) - } else { - log.G(ctx).Debugf("ReopenContainerLog for %q returns successfully", r.GetContainerId()) - } - }() - res, err = in.c.ReopenContainerLog(ctrdutil.WithNamespace(ctx), r) - return res, errdefs.ToGRPC(err) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/io/container_io.go b/vendor/github.com/containerd/cri/pkg/server/io/container_io.go deleted file mode 100644 index c66549ca5..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/io/container_io.go +++ /dev/null @@ -1,236 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package io - -import ( - "errors" - "io" - "strings" - "sync" - - "github.com/containerd/containerd/cio" - "github.com/sirupsen/logrus" - - cioutil "github.com/containerd/cri/pkg/ioutil" - "github.com/containerd/cri/pkg/util" -) - -// streamKey generates a key for the stream. -func streamKey(id, name string, stream StreamType) string { - return strings.Join([]string{id, name, string(stream)}, "-") -} - -// ContainerIO holds the container io. -type ContainerIO struct { - id string - - fifos *cio.FIFOSet - *stdioPipes - - stdoutGroup *cioutil.WriterGroup - stderrGroup *cioutil.WriterGroup - - closer *wgCloser -} - -var _ cio.IO = &ContainerIO{} - -// ContainerIOOpts sets specific information to newly created ContainerIO. -type ContainerIOOpts func(*ContainerIO) error - -// WithFIFOs specifies existing fifos for the container io. -func WithFIFOs(fifos *cio.FIFOSet) ContainerIOOpts { - return func(c *ContainerIO) error { - c.fifos = fifos - return nil - } -} - -// WithNewFIFOs creates new fifos for the container io. -func WithNewFIFOs(root string, tty, stdin bool) ContainerIOOpts { - return func(c *ContainerIO) error { - fifos, err := newFifos(root, c.id, tty, stdin) - if err != nil { - return err - } - return WithFIFOs(fifos)(c) - } -} - -// NewContainerIO creates container io. -func NewContainerIO(id string, opts ...ContainerIOOpts) (_ *ContainerIO, err error) { - c := &ContainerIO{ - id: id, - stdoutGroup: cioutil.NewWriterGroup(), - stderrGroup: cioutil.NewWriterGroup(), - } - for _, opt := range opts { - if err := opt(c); err != nil { - return nil, err - } - } - if c.fifos == nil { - return nil, errors.New("fifos are not set") - } - // Create actual fifos. - stdio, closer, err := newStdioPipes(c.fifos) - if err != nil { - return nil, err - } - c.stdioPipes = stdio - c.closer = closer - return c, nil -} - -// Config returns io config. -func (c *ContainerIO) Config() cio.Config { - return c.fifos.Config -} - -// Pipe creates container fifos and pipe container output -// to output stream. -func (c *ContainerIO) Pipe() { - wg := c.closer.wg - if c.stdout != nil { - wg.Add(1) - go func() { - if _, err := io.Copy(c.stdoutGroup, c.stdout); err != nil { - logrus.WithError(err).Errorf("Failed to pipe stdout of container %q", c.id) - } - c.stdout.Close() - c.stdoutGroup.Close() - wg.Done() - logrus.Infof("Finish piping stdout of container %q", c.id) - }() - } - - if !c.fifos.Terminal && c.stderr != nil { - wg.Add(1) - go func() { - if _, err := io.Copy(c.stderrGroup, c.stderr); err != nil { - logrus.WithError(err).Errorf("Failed to pipe stderr of container %q", c.id) - } - c.stderr.Close() - c.stderrGroup.Close() - wg.Done() - logrus.Infof("Finish piping stderr of container %q", c.id) - }() - } -} - -// Attach attaches container stdio. -// TODO(random-liu): Use pools.Copy in docker to reduce memory usage? -func (c *ContainerIO) Attach(opts AttachOptions) { - var wg sync.WaitGroup - key := util.GenerateID() - stdinKey := streamKey(c.id, "attach-"+key, Stdin) - stdoutKey := streamKey(c.id, "attach-"+key, Stdout) - stderrKey := streamKey(c.id, "attach-"+key, Stderr) - - var stdinStreamRC io.ReadCloser - if c.stdin != nil && opts.Stdin != nil { - // Create a wrapper of stdin which could be closed. Note that the - // wrapper doesn't close the actual stdin, it only stops io.Copy. - // The actual stdin will be closed by stream server. - stdinStreamRC = cioutil.NewWrapReadCloser(opts.Stdin) - wg.Add(1) - go func() { - if _, err := io.Copy(c.stdin, stdinStreamRC); err != nil { - logrus.WithError(err).Errorf("Failed to pipe stdin for container attach %q", c.id) - } - logrus.Infof("Attach stream %q closed", stdinKey) - if opts.StdinOnce && !opts.Tty { - // Due to kubectl requirements and current docker behavior, when (opts.StdinOnce && - // opts.Tty) we have to close container stdin and keep stdout and stderr open until - // container stops. - c.stdin.Close() - // Also closes the containerd side. - if err := opts.CloseStdin(); err != nil { - logrus.WithError(err).Errorf("Failed to close stdin for container %q", c.id) - } - } else { - if opts.Stdout != nil { - c.stdoutGroup.Remove(stdoutKey) - } - if opts.Stderr != nil { - c.stderrGroup.Remove(stderrKey) - } - } - wg.Done() - }() - } - - attachStream := func(key string, close <-chan struct{}) { - <-close - logrus.Infof("Attach stream %q closed", key) - // Make sure stdin gets closed. - if stdinStreamRC != nil { - stdinStreamRC.Close() - } - wg.Done() - } - - if opts.Stdout != nil { - wg.Add(1) - wc, close := cioutil.NewWriteCloseInformer(opts.Stdout) - c.stdoutGroup.Add(stdoutKey, wc) - go attachStream(stdoutKey, close) - } - if !opts.Tty && opts.Stderr != nil { - wg.Add(1) - wc, close := cioutil.NewWriteCloseInformer(opts.Stderr) - c.stderrGroup.Add(stderrKey, wc) - go attachStream(stderrKey, close) - } - wg.Wait() -} - -// AddOutput adds new write closers to the container stream, and returns existing -// write closers if there are any. -func (c *ContainerIO) AddOutput(name string, stdout, stderr io.WriteCloser) (io.WriteCloser, io.WriteCloser) { - var oldStdout, oldStderr io.WriteCloser - if stdout != nil { - key := streamKey(c.id, name, Stdout) - oldStdout = c.stdoutGroup.Get(key) - c.stdoutGroup.Add(key, stdout) - } - if stderr != nil { - key := streamKey(c.id, name, Stderr) - oldStderr = c.stderrGroup.Get(key) - c.stderrGroup.Add(key, stderr) - } - return oldStdout, oldStderr -} - -// Cancel cancels container io. -func (c *ContainerIO) Cancel() { - c.closer.Cancel() -} - -// Wait waits container io to finish. -func (c *ContainerIO) Wait() { - c.closer.Wait() -} - -// Close closes all FIFOs. -func (c *ContainerIO) Close() error { - c.closer.Close() - if c.fifos != nil { - return c.fifos.Close() - } - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/io/exec_io.go b/vendor/github.com/containerd/cri/pkg/server/io/exec_io.go deleted file mode 100644 index 4a695030d..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/io/exec_io.go +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package io - -import ( - "io" - "sync" - - "github.com/containerd/containerd/cio" - "github.com/sirupsen/logrus" - - cioutil "github.com/containerd/cri/pkg/ioutil" -) - -// ExecIO holds the exec io. -type ExecIO struct { - id string - fifos *cio.FIFOSet - *stdioPipes - closer *wgCloser -} - -var _ cio.IO = &ExecIO{} - -// NewExecIO creates exec io. -func NewExecIO(id, root string, tty, stdin bool) (*ExecIO, error) { - fifos, err := newFifos(root, id, tty, stdin) - if err != nil { - return nil, err - } - stdio, closer, err := newStdioPipes(fifos) - if err != nil { - return nil, err - } - return &ExecIO{ - id: id, - fifos: fifos, - stdioPipes: stdio, - closer: closer, - }, nil -} - -// Config returns io config. -func (e *ExecIO) Config() cio.Config { - return e.fifos.Config -} - -// Attach attaches exec stdio. The logic is similar with container io attach. -func (e *ExecIO) Attach(opts AttachOptions) <-chan struct{} { - var wg sync.WaitGroup - var stdinStreamRC io.ReadCloser - if e.stdin != nil && opts.Stdin != nil { - stdinStreamRC = cioutil.NewWrapReadCloser(opts.Stdin) - wg.Add(1) - go func() { - if _, err := io.Copy(e.stdin, stdinStreamRC); err != nil { - logrus.WithError(err).Errorf("Failed to redirect stdin for container exec %q", e.id) - } - logrus.Infof("Container exec %q stdin closed", e.id) - if opts.StdinOnce && !opts.Tty { - e.stdin.Close() - if err := opts.CloseStdin(); err != nil { - logrus.WithError(err).Errorf("Failed to close stdin for container exec %q", e.id) - } - } else { - if e.stdout != nil { - e.stdout.Close() - } - if e.stderr != nil { - e.stderr.Close() - } - } - wg.Done() - }() - } - - attachOutput := func(t StreamType, stream io.WriteCloser, out io.ReadCloser) { - if _, err := io.Copy(stream, out); err != nil { - logrus.WithError(err).Errorf("Failed to pipe %q for container exec %q", t, e.id) - } - out.Close() - stream.Close() - if stdinStreamRC != nil { - stdinStreamRC.Close() - } - e.closer.wg.Done() - wg.Done() - logrus.Infof("Finish piping %q of container exec %q", t, e.id) - } - - if opts.Stdout != nil { - wg.Add(1) - // Closer should wait for this routine to be over. - e.closer.wg.Add(1) - go attachOutput(Stdout, opts.Stdout, e.stdout) - } - - if !opts.Tty && opts.Stderr != nil { - wg.Add(1) - // Closer should wait for this routine to be over. - e.closer.wg.Add(1) - go attachOutput(Stderr, opts.Stderr, e.stderr) - } - - done := make(chan struct{}) - go func() { - wg.Wait() - close(done) - }() - return done -} - -// Cancel cancels exec io. -func (e *ExecIO) Cancel() { - e.closer.Cancel() -} - -// Wait waits exec io to finish. -func (e *ExecIO) Wait() { - e.closer.Wait() -} - -// Close closes all FIFOs. -func (e *ExecIO) Close() error { - if e.closer != nil { - e.closer.Close() - } - if e.fifos != nil { - return e.fifos.Close() - } - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/io/helpers.go b/vendor/github.com/containerd/cri/pkg/server/io/helpers.go deleted file mode 100644 index 59d41411f..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/io/helpers.go +++ /dev/null @@ -1,144 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package io - -import ( - "io" - "os" - "path/filepath" - "sync" - "syscall" - - "github.com/containerd/containerd/cio" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// AttachOptions specifies how to attach to a container. -type AttachOptions struct { - Stdin io.Reader - Stdout io.WriteCloser - Stderr io.WriteCloser - Tty bool - StdinOnce bool - // CloseStdin is the function to close container stdin. - CloseStdin func() error -} - -// StreamType is the type of the stream, stdout/stderr. -type StreamType string - -const ( - // Stdin stream type. - Stdin StreamType = "stdin" - // Stdout stream type. - Stdout StreamType = StreamType(runtime.Stdout) - // Stderr stream type. - Stderr StreamType = StreamType(runtime.Stderr) -) - -type wgCloser struct { - ctx context.Context - wg *sync.WaitGroup - set []io.Closer - cancel context.CancelFunc -} - -func (g *wgCloser) Wait() { - g.wg.Wait() -} - -func (g *wgCloser) Close() { - for _, f := range g.set { - f.Close() - } -} - -func (g *wgCloser) Cancel() { - g.cancel() -} - -// newFifos creates fifos directory for a container. -func newFifos(root, id string, tty, stdin bool) (*cio.FIFOSet, error) { - root = filepath.Join(root, "io") - if err := os.MkdirAll(root, 0700); err != nil { - return nil, err - } - fifos, err := cio.NewFIFOSetInDir(root, id, tty) - if err != nil { - return nil, err - } - if !stdin { - fifos.Stdin = "" - } - return fifos, nil -} - -type stdioPipes struct { - stdin io.WriteCloser - stdout io.ReadCloser - stderr io.ReadCloser -} - -// newStdioPipes creates actual fifos for stdio. -func newStdioPipes(fifos *cio.FIFOSet) (_ *stdioPipes, _ *wgCloser, err error) { - var ( - f io.ReadWriteCloser - set []io.Closer - ctx, cancel = context.WithCancel(context.Background()) - p = &stdioPipes{} - ) - defer func() { - if err != nil { - for _, f := range set { - f.Close() - } - cancel() - } - }() - - if fifos.Stdin != "" { - if f, err = openPipe(ctx, fifos.Stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, nil, err - } - p.stdin = f - set = append(set, f) - } - - if fifos.Stdout != "" { - if f, err = openPipe(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, nil, err - } - p.stdout = f - set = append(set, f) - } - - if fifos.Stderr != "" { - if f, err = openPipe(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, nil, err - } - p.stderr = f - set = append(set, f) - } - - return p, &wgCloser{ - wg: &sync.WaitGroup{}, - set: set, - ctx: ctx, - cancel: cancel, - }, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/io/helpers_unix.go b/vendor/github.com/containerd/cri/pkg/server/io/helpers_unix.go deleted file mode 100644 index 2780b958a..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/io/helpers_unix.go +++ /dev/null @@ -1,31 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package io - -import ( - "io" - "os" - - "github.com/containerd/fifo" - "golang.org/x/net/context" -) - -func openPipe(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) { - return fifo.OpenFifo(ctx, fn, flag, perm) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/io/helpers_windows.go b/vendor/github.com/containerd/cri/pkg/server/io/helpers_windows.go deleted file mode 100644 index f64807edf..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/io/helpers_windows.go +++ /dev/null @@ -1,81 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package io - -import ( - "io" - "net" - "os" - "sync" - - winio "github.com/Microsoft/go-winio" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -type pipe struct { - l net.Listener - con net.Conn - conErr error - conWg sync.WaitGroup -} - -func openPipe(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) { - l, err := winio.ListenPipe(fn, nil) - if err != nil { - return nil, err - } - p := &pipe{l: l} - p.conWg.Add(1) - go func() { - defer p.conWg.Done() - c, err := l.Accept() - if err != nil { - p.conErr = err - return - } - p.con = c - }() - return p, nil -} - -func (p *pipe) Write(b []byte) (int, error) { - p.conWg.Wait() - if p.conErr != nil { - return 0, errors.Wrap(p.conErr, "connection error") - } - return p.con.Write(b) -} - -func (p *pipe) Read(b []byte) (int, error) { - p.conWg.Wait() - if p.conErr != nil { - return 0, errors.Wrap(p.conErr, "connection error") - } - return p.con.Read(b) -} - -func (p *pipe) Close() error { - p.l.Close() - p.conWg.Wait() - if p.con != nil { - return p.con.Close() - } - return p.conErr -} diff --git a/vendor/github.com/containerd/cri/pkg/server/io/logger.go b/vendor/github.com/containerd/cri/pkg/server/io/logger.go deleted file mode 100644 index f13b6f8bf..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/io/logger.go +++ /dev/null @@ -1,196 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package io - -import ( - "bufio" - "bytes" - "fmt" - "io" - "io/ioutil" - "time" - - "github.com/sirupsen/logrus" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - cioutil "github.com/containerd/cri/pkg/ioutil" -) - -const ( - // delimiter used in CRI logging format. - delimiter = ' ' - // eof is end-of-line. - eol = '\n' - // timestampFormat is the timestamp format used in CRI logging format. - timestampFormat = time.RFC3339Nano - // defaultBufSize is the default size of the read buffer in bytes. - defaultBufSize = 4096 -) - -// NewDiscardLogger creates logger which discards all the input. -func NewDiscardLogger() io.WriteCloser { - return cioutil.NewNopWriteCloser(ioutil.Discard) -} - -// NewCRILogger returns a write closer which redirect container log into -// log file, and decorate the log line into CRI defined format. It also -// returns a channel which indicates whether the logger is stopped. -// maxLen is the max length limit of a line. A line longer than the -// limit will be cut into multiple lines. -func NewCRILogger(path string, w io.Writer, stream StreamType, maxLen int) (io.WriteCloser, <-chan struct{}) { - logrus.Debugf("Start writing stream %q to log file %q", stream, path) - prc, pwc := io.Pipe() - stop := make(chan struct{}) - go func() { - redirectLogs(path, prc, w, stream, maxLen) - close(stop) - }() - return pwc, stop -} - -// bufio.ReadLine in golang eats both read errors and tailing newlines -// (See https://golang.org/pkg/bufio/#Reader.ReadLine). When reading -// to io.EOF, it is impossible for the caller to figure out whether -// there is a newline at the end, for example: -// 1) When reading "CONTENT\n", it returns "CONTENT" without error; -// 2) When reading "CONTENT", it also returns "CONTENT" without error. -// -// To differentiate these 2 cases, we need to write a readLine function -// ourselves to not ignore the error. -// -// The code is similar with https://golang.org/src/bufio/bufio.go?s=9537:9604#L359. -// The only difference is that it returns all errors from `ReadSlice`. -// -// readLine returns err != nil if and only if line does not end with a new line. -func readLine(b *bufio.Reader) (line []byte, isPrefix bool, err error) { - line, err = b.ReadSlice('\n') - if err == bufio.ErrBufferFull { - // Handle the case where "\r\n" straddles the buffer. - if len(line) > 0 && line[len(line)-1] == '\r' { - // Unread the last '\r' - if err := b.UnreadByte(); err != nil { - panic(fmt.Sprintf("invalid unread %v", err)) - } - line = line[:len(line)-1] - } - return line, true, nil - } - - if len(line) == 0 { - if err != nil { - line = nil - } - return - } - - if line[len(line)-1] == '\n' { - // "ReadSlice returns err != nil if and only if line does not end in delim" - // (See https://golang.org/pkg/bufio/#Reader.ReadSlice). - if err != nil { - panic(fmt.Sprintf("full read with unexpected error %v", err)) - } - drop := 1 - if len(line) > 1 && line[len(line)-2] == '\r' { - drop = 2 - } - line = line[:len(line)-drop] - } - return -} - -func redirectLogs(path string, rc io.ReadCloser, w io.Writer, s StreamType, maxLen int) { - defer rc.Close() - var ( - stream = []byte(s) - delimiter = []byte{delimiter} - partial = []byte(runtime.LogTagPartial) - full = []byte(runtime.LogTagFull) - buf [][]byte - length int - bufSize = defaultBufSize - ) - // Make sure bufSize <= maxLen - if maxLen > 0 && maxLen < bufSize { - bufSize = maxLen - } - r := bufio.NewReaderSize(rc, bufSize) - writeLine := func(tag, line []byte) { - timestamp := time.Now().AppendFormat(nil, timestampFormat) - data := bytes.Join([][]byte{timestamp, stream, tag, line}, delimiter) - data = append(data, eol) - if _, err := w.Write(data); err != nil { - logrus.WithError(err).Errorf("Fail to write %q log to log file %q", s, path) - // Continue on write error to drain the container output. - } - } - for { - var stop bool - newLine, isPrefix, err := readLine(r) - // NOTE(random-liu): readLine can return actual content even if there is an error. - if len(newLine) > 0 { - // Buffer returned by ReadLine will change after - // next read, copy it. - l := make([]byte, len(newLine)) - copy(l, newLine) - buf = append(buf, l) - length += len(l) - } - if err != nil { - if err == io.EOF { - logrus.Debugf("Getting EOF from stream %q while redirecting to log file %q", s, path) - } else { - logrus.WithError(err).Errorf("An error occurred when redirecting stream %q to log file %q", s, path) - } - if length == 0 { - // No content left to write, break. - break - } - // Stop after writing the content left in buffer. - stop = true - } - if maxLen > 0 && length > maxLen { - exceedLen := length - maxLen - last := buf[len(buf)-1] - if exceedLen > len(last) { - // exceedLen must <= len(last), or else the buffer - // should have be written in the previous iteration. - panic("exceed length should <= last buffer size") - } - buf[len(buf)-1] = last[:len(last)-exceedLen] - writeLine(partial, bytes.Join(buf, nil)) - buf = [][]byte{last[len(last)-exceedLen:]} - length = exceedLen - } - if isPrefix { - continue - } - if stop { - // readLine only returns error when the message doesn't - // end with a newline, in that case it should be treated - // as a partial line. - writeLine(partial, bytes.Join(buf, nil)) - } else { - writeLine(full, bytes.Join(buf, nil)) - } - buf = nil - length = 0 - if stop { - break - } - } - logrus.Debugf("Finish redirecting stream %q to log file %q", s, path) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/opts.go b/vendor/github.com/containerd/cri/pkg/server/opts.go deleted file mode 100644 index 58520dbc3..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/opts.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "context" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/log" - "github.com/containerd/nri" - v1 "github.com/containerd/nri/types/v1" -) - -// WithNRISandboxDelete calls delete for a sandbox'd task -func WithNRISandboxDelete(sandboxID string) containerd.ProcessDeleteOpts { - return func(ctx context.Context, p containerd.Process) error { - task, ok := p.(containerd.Task) - if !ok { - return nil - } - nric, err := nri.New() - if err != nil { - log.G(ctx).WithError(err).Error("unable to create nri client") - return nil - } - if nric == nil { - return nil - } - sb := &nri.Sandbox{ - ID: sandboxID, - } - if _, err := nric.InvokeWithSandbox(ctx, task, v1.Delete, sb); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to delete nri for %q", task.ID()) - } - return nil - } -} diff --git a/vendor/github.com/containerd/cri/pkg/server/restart.go b/vendor/github.com/containerd/cri/pkg/server/restart.go deleted file mode 100644 index 2480bd5ea..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/restart.go +++ /dev/null @@ -1,483 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "io/ioutil" - "os" - "path/filepath" - goruntime "runtime" - "time" - - "github.com/containerd/containerd" - containerdio "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" - containerdimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/platforms" - "github.com/containerd/typeurl" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/netns" - cio "github.com/containerd/cri/pkg/server/io" - containerstore "github.com/containerd/cri/pkg/store/container" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -// NOTE: The recovery logic has following assumption: when the cri plugin is down: -// 1) Files (e.g. root directory, netns) and checkpoint maintained by the plugin MUST NOT be -// touched. Or else, recovery logic for those containers/sandboxes may return error. -// 2) Containerd containers may be deleted, but SHOULD NOT be added. Or else, recovery logic -// for the newly added container/sandbox will return error, because there is no corresponding root -// directory created. -// 3) Containerd container tasks may exit or be stoppped, deleted. Even though current logic could -// tolerant tasks being created or started, we prefer that not to happen. - -// recover recovers system state from containerd and status checkpoint. -func (c *criService) recover(ctx context.Context) error { - // Recover all sandboxes. - sandboxes, err := c.client.Containers(ctx, filterLabel(containerKindLabel, containerKindSandbox)) - if err != nil { - return errors.Wrap(err, "failed to list sandbox containers") - } - for _, sandbox := range sandboxes { - sb, err := c.loadSandbox(ctx, sandbox) - if err != nil { - log.G(ctx).WithError(err).Errorf("Failed to load sandbox %q", sandbox.ID()) - continue - } - log.G(ctx).Debugf("Loaded sandbox %+v", sb) - if err := c.sandboxStore.Add(sb); err != nil { - return errors.Wrapf(err, "failed to add sandbox %q to store", sandbox.ID()) - } - if err := c.sandboxNameIndex.Reserve(sb.Name, sb.ID); err != nil { - return errors.Wrapf(err, "failed to reserve sandbox name %q", sb.Name) - } - } - - // Recover all containers. - containers, err := c.client.Containers(ctx, filterLabel(containerKindLabel, containerKindContainer)) - if err != nil { - return errors.Wrap(err, "failed to list containers") - } - for _, container := range containers { - cntr, err := c.loadContainer(ctx, container) - if err != nil { - log.G(ctx).WithError(err).Errorf("Failed to load container %q", container.ID()) - continue - } - log.G(ctx).Debugf("Loaded container %+v", cntr) - if err := c.containerStore.Add(cntr); err != nil { - return errors.Wrapf(err, "failed to add container %q to store", container.ID()) - } - if err := c.containerNameIndex.Reserve(cntr.Name, cntr.ID); err != nil { - return errors.Wrapf(err, "failed to reserve container name %q", cntr.Name) - } - } - - // Recover all images. - cImages, err := c.client.ListImages(ctx) - if err != nil { - return errors.Wrap(err, "failed to list images") - } - c.loadImages(ctx, cImages) - - // It's possible that containerd containers are deleted unexpectedly. In that case, - // we can't even get metadata, we should cleanup orphaned sandbox/container directories - // with best effort. - - // Cleanup orphaned sandbox and container directories without corresponding containerd container. - for _, cleanup := range []struct { - cntrs []containerd.Container - base string - errMsg string - }{ - { - cntrs: sandboxes, - base: filepath.Join(c.config.RootDir, sandboxesDir), - errMsg: "failed to cleanup orphaned sandbox directories", - }, - { - cntrs: sandboxes, - base: filepath.Join(c.config.StateDir, sandboxesDir), - errMsg: "failed to cleanup orphaned volatile sandbox directories", - }, - { - cntrs: containers, - base: filepath.Join(c.config.RootDir, containersDir), - errMsg: "failed to cleanup orphaned container directories", - }, - { - cntrs: containers, - base: filepath.Join(c.config.StateDir, containersDir), - errMsg: "failed to cleanup orphaned volatile container directories", - }, - } { - if err := cleanupOrphanedIDDirs(ctx, cleanup.cntrs, cleanup.base); err != nil { - return errors.Wrap(err, cleanup.errMsg) - } - } - return nil -} - -// loadContainerTimeout is the default timeout for loading a container/sandbox. -// One container/sandbox hangs (e.g. containerd#2438) should not affect other -// containers/sandboxes. -// Most CRI container/sandbox related operations are per container, the ones -// which handle multiple containers at a time are: -// * ListPodSandboxes: Don't talk with containerd services. -// * ListContainers: Don't talk with containerd services. -// * ListContainerStats: Not in critical code path, a default timeout will -// be applied at CRI level. -// * Recovery logic: We should set a time for each container/sandbox recovery. -// * Event monitor: We should set a timeout for each container/sandbox event handling. -const loadContainerTimeout = 10 * time.Second - -// loadContainer loads container from containerd and status checkpoint. -func (c *criService) loadContainer(ctx context.Context, cntr containerd.Container) (containerstore.Container, error) { - ctx, cancel := context.WithTimeout(ctx, loadContainerTimeout) - defer cancel() - id := cntr.ID() - containerDir := c.getContainerRootDir(id) - volatileContainerDir := c.getVolatileContainerRootDir(id) - var container containerstore.Container - // Load container metadata. - exts, err := cntr.Extensions(ctx) - if err != nil { - return container, errors.Wrap(err, "failed to get container extensions") - } - ext, ok := exts[containerMetadataExtension] - if !ok { - return container, errors.Errorf("metadata extension %q not found", containerMetadataExtension) - } - data, err := typeurl.UnmarshalAny(&ext) - if err != nil { - return container, errors.Wrapf(err, "failed to unmarshal metadata extension %q", ext) - } - meta := data.(*containerstore.Metadata) - - // Load status from checkpoint. - status, err := containerstore.LoadStatus(containerDir, id) - if err != nil { - log.G(ctx).WithError(err).Warnf("Failed to load container status for %q", id) - status = unknownContainerStatus() - } - - var containerIO *cio.ContainerIO - err = func() error { - // Load up-to-date status from containerd. - t, err := cntr.Task(ctx, func(fifos *containerdio.FIFOSet) (_ containerdio.IO, err error) { - stdoutWC, stderrWC, err := c.createContainerLoggers(meta.LogPath, meta.Config.GetTty()) - if err != nil { - return nil, err - } - defer func() { - if err != nil { - if stdoutWC != nil { - stdoutWC.Close() - } - if stderrWC != nil { - stderrWC.Close() - } - } - }() - containerIO, err = cio.NewContainerIO(id, - cio.WithFIFOs(fifos), - ) - if err != nil { - return nil, err - } - containerIO.AddOutput("log", stdoutWC, stderrWC) - containerIO.Pipe() - return containerIO, nil - }) - if err != nil && !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to load task") - } - var s containerd.Status - var notFound bool - if errdefs.IsNotFound(err) { - // Task is not found. - notFound = true - } else { - // Task is found. Get task status. - s, err = t.Status(ctx) - if err != nil { - // It's still possible that task is deleted during this window. - if !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to get task status") - } - notFound = true - } - } - if notFound { - // Task is not created or has been deleted, use the checkpointed status - // to generate container status. - switch status.State() { - case runtime.ContainerState_CONTAINER_CREATED: - // NOTE: Another possibility is that we've tried to start the container, but - // containerd got restarted during that. In that case, we still - // treat the container as `CREATED`. - containerIO, err = cio.NewContainerIO(id, - cio.WithNewFIFOs(volatileContainerDir, meta.Config.GetTty(), meta.Config.GetStdin()), - ) - if err != nil { - return errors.Wrap(err, "failed to create container io") - } - case runtime.ContainerState_CONTAINER_RUNNING: - // Container was in running state, but its task has been deleted, - // set unknown exited state. Container io is not needed in this case. - status.FinishedAt = time.Now().UnixNano() - status.ExitCode = unknownExitCode - status.Reason = unknownExitReason - default: - // Container is in exited/unknown state, return the status as it is. - } - } else { - // Task status is found. Update container status based on the up-to-date task status. - switch s.Status { - case containerd.Created: - // Task has been created, but not started yet. This could only happen if containerd - // gets restarted during container start. - // Container must be in `CREATED` state. - if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to delete task") - } - if status.State() != runtime.ContainerState_CONTAINER_CREATED { - return errors.Errorf("unexpected container state for created task: %q", status.State()) - } - case containerd.Running: - // Task is running. Container must be in `RUNNING` state, based on our assuption that - // "task should not be started when containerd is down". - switch status.State() { - case runtime.ContainerState_CONTAINER_EXITED: - return errors.Errorf("unexpected container state for running task: %q", status.State()) - case runtime.ContainerState_CONTAINER_RUNNING: - default: - // This may happen if containerd gets restarted after task is started, but - // before status is checkpointed. - status.StartedAt = time.Now().UnixNano() - status.Pid = t.Pid() - } - // Wait for the task for exit monitor. - // wait is a long running background request, no timeout needed. - exitCh, err := t.Wait(ctrdutil.NamespacedContext()) - if err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to wait for task") - } - // Container was in running state, but its task has been deleted, - // set unknown exited state. - status.FinishedAt = time.Now().UnixNano() - status.ExitCode = unknownExitCode - status.Reason = unknownExitReason - } else { - // Start exit monitor. - c.eventMonitor.startExitMonitor(context.Background(), id, status.Pid, exitCh) - } - case containerd.Stopped: - // Task is stopped. Updata status and delete the task. - if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to delete task") - } - status.FinishedAt = s.ExitTime.UnixNano() - status.ExitCode = int32(s.ExitStatus) - default: - return errors.Errorf("unexpected task status %q", s.Status) - } - } - return nil - }() - if err != nil { - log.G(ctx).WithError(err).Errorf("Failed to load container status for %q", id) - // Only set the unknown field in this case, because other fields may - // contain useful information loaded from the checkpoint. - status.Unknown = true - } - opts := []containerstore.Opts{ - containerstore.WithStatus(status, containerDir), - containerstore.WithContainer(cntr), - } - // containerIO could be nil for container in unknown state. - if containerIO != nil { - opts = append(opts, containerstore.WithContainerIO(containerIO)) - } - return containerstore.NewContainer(*meta, opts...) -} - -// loadSandbox loads sandbox from containerd. -func (c *criService) loadSandbox(ctx context.Context, cntr containerd.Container) (sandboxstore.Sandbox, error) { - ctx, cancel := context.WithTimeout(ctx, loadContainerTimeout) - defer cancel() - var sandbox sandboxstore.Sandbox - // Load sandbox metadata. - exts, err := cntr.Extensions(ctx) - if err != nil { - return sandbox, errors.Wrap(err, "failed to get sandbox container extensions") - } - ext, ok := exts[sandboxMetadataExtension] - if !ok { - return sandbox, errors.Errorf("metadata extension %q not found", sandboxMetadataExtension) - } - data, err := typeurl.UnmarshalAny(&ext) - if err != nil { - return sandbox, errors.Wrapf(err, "failed to unmarshal metadata extension %q", ext) - } - meta := data.(*sandboxstore.Metadata) - - s, err := func() (sandboxstore.Status, error) { - status := unknownSandboxStatus() - // Load sandbox created timestamp. - info, err := cntr.Info(ctx) - if err != nil { - return status, errors.Wrap(err, "failed to get sandbox container info") - } - status.CreatedAt = info.CreatedAt - - // Load sandbox state. - t, err := cntr.Task(ctx, nil) - if err != nil && !errdefs.IsNotFound(err) { - return status, errors.Wrap(err, "failed to load task") - } - var taskStatus containerd.Status - var notFound bool - if errdefs.IsNotFound(err) { - // Task is not found. - notFound = true - } else { - // Task is found. Get task status. - taskStatus, err = t.Status(ctx) - if err != nil { - // It's still possible that task is deleted during this window. - if !errdefs.IsNotFound(err) { - return status, errors.Wrap(err, "failed to get task status") - } - notFound = true - } - } - if notFound { - // Task does not exist, set sandbox state as NOTREADY. - status.State = sandboxstore.StateNotReady - } else { - if taskStatus.Status == containerd.Running { - // Wait for the task for sandbox monitor. - // wait is a long running background request, no timeout needed. - exitCh, err := t.Wait(ctrdutil.NamespacedContext()) - if err != nil { - if !errdefs.IsNotFound(err) { - return status, errors.Wrap(err, "failed to wait for task") - } - status.State = sandboxstore.StateNotReady - } else { - // Task is running, set sandbox state as READY. - status.State = sandboxstore.StateReady - status.Pid = t.Pid() - c.eventMonitor.startExitMonitor(context.Background(), meta.ID, status.Pid, exitCh) - } - } else { - // Task is not running. Delete the task and set sandbox state as NOTREADY. - if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - return status, errors.Wrap(err, "failed to delete task") - } - status.State = sandboxstore.StateNotReady - } - } - return status, nil - }() - if err != nil { - log.G(ctx).WithError(err).Errorf("Failed to load sandbox status for %q", cntr.ID()) - } - - sandbox = sandboxstore.NewSandbox(*meta, s) - sandbox.Container = cntr - - // Load network namespace. - if goruntime.GOOS != "windows" && - meta.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { - // Don't need to load netns for host network sandbox. - return sandbox, nil - } - sandbox.NetNS = netns.LoadNetNS(meta.NetNSPath) - - // It doesn't matter whether task is running or not. If it is running, sandbox - // status will be `READY`; if it is not running, sandbox status will be `NOT_READY`, - // kubelet will stop the sandbox which will properly cleanup everything. - return sandbox, nil -} - -// loadImages loads images from containerd. -func (c *criService) loadImages(ctx context.Context, cImages []containerd.Image) { - snapshotter := c.config.ContainerdConfig.Snapshotter - for _, i := range cImages { - ok, _, _, _, err := containerdimages.Check(ctx, i.ContentStore(), i.Target(), platforms.Default()) - if err != nil { - log.G(ctx).WithError(err).Errorf("Failed to check image content readiness for %q", i.Name()) - continue - } - if !ok { - log.G(ctx).Warnf("The image content readiness for %q is not ok", i.Name()) - continue - } - // Checking existence of top-level snapshot for each image being recovered. - unpacked, err := i.IsUnpacked(ctx, snapshotter) - if err != nil { - log.G(ctx).WithError(err).Warnf("Failed to check whether image is unpacked for image %s", i.Name()) - continue - } - if !unpacked { - log.G(ctx).Warnf("The image %s is not unpacked.", i.Name()) - // TODO(random-liu): Consider whether we should try unpack here. - } - if err := c.updateImage(ctx, i.Name()); err != nil { - log.G(ctx).WithError(err).Warnf("Failed to update reference for image %q", i.Name()) - continue - } - log.G(ctx).Debugf("Loaded image %q", i.Name()) - } -} - -func cleanupOrphanedIDDirs(ctx context.Context, cntrs []containerd.Container, base string) error { - // Cleanup orphaned id directories. - dirs, err := ioutil.ReadDir(base) - if err != nil && !os.IsNotExist(err) { - return errors.Wrap(err, "failed to read base directory") - } - idsMap := make(map[string]containerd.Container) - for _, cntr := range cntrs { - idsMap[cntr.ID()] = cntr - } - for _, d := range dirs { - if !d.IsDir() { - log.G(ctx).Warnf("Invalid file %q found in base directory %q", d.Name(), base) - continue - } - if _, ok := idsMap[d.Name()]; ok { - // Do not remove id directory if corresponding container is found. - continue - } - dir := filepath.Join(base, d.Name()) - if err := ensureRemoveAll(ctx, dir); err != nil { - log.G(ctx).WithError(err).Warnf("Failed to remove id directory %q", dir) - } else { - log.G(ctx).Debugf("Cleanup orphaned id directory %q", dir) - } - } - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_list.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_list.go deleted file mode 100644 index d2528b267..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_list.go +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -// ListPodSandbox returns a list of Sandbox. -func (c *criService) ListPodSandbox(ctx context.Context, r *runtime.ListPodSandboxRequest) (*runtime.ListPodSandboxResponse, error) { - // List all sandboxes from store. - sandboxesInStore := c.sandboxStore.List() - var sandboxes []*runtime.PodSandbox - for _, sandboxInStore := range sandboxesInStore { - sandboxes = append(sandboxes, toCRISandbox( - sandboxInStore.Metadata, - sandboxInStore.Status.Get(), - )) - } - - sandboxes = c.filterCRISandboxes(sandboxes, r.GetFilter()) - return &runtime.ListPodSandboxResponse{Items: sandboxes}, nil -} - -// toCRISandbox converts sandbox metadata into CRI pod sandbox. -func toCRISandbox(meta sandboxstore.Metadata, status sandboxstore.Status) *runtime.PodSandbox { - // Set sandbox state to NOTREADY by default. - state := runtime.PodSandboxState_SANDBOX_NOTREADY - if status.State == sandboxstore.StateReady { - state = runtime.PodSandboxState_SANDBOX_READY - } - return &runtime.PodSandbox{ - Id: meta.ID, - Metadata: meta.Config.GetMetadata(), - State: state, - CreatedAt: status.CreatedAt.UnixNano(), - Labels: meta.Config.GetLabels(), - Annotations: meta.Config.GetAnnotations(), - RuntimeHandler: meta.RuntimeHandler, - } -} - -func (c *criService) normalizePodSandboxFilter(filter *runtime.PodSandboxFilter) { - if sb, err := c.sandboxStore.Get(filter.GetId()); err == nil { - filter.Id = sb.ID - } -} - -// filterCRISandboxes filters CRISandboxes. -func (c *criService) filterCRISandboxes(sandboxes []*runtime.PodSandbox, filter *runtime.PodSandboxFilter) []*runtime.PodSandbox { - if filter == nil { - return sandboxes - } - - c.normalizePodSandboxFilter(filter) - filtered := []*runtime.PodSandbox{} - for _, s := range sandboxes { - // Filter by id - if filter.GetId() != "" && filter.GetId() != s.Id { - continue - } - // Filter by state - if filter.GetState() != nil && filter.GetState().GetState() != s.State { - continue - } - // Filter by label - if filter.GetLabelSelector() != nil { - match := true - for k, v := range filter.GetLabelSelector() { - got, ok := s.Labels[k] - if !ok || got != v { - match = false - break - } - } - if !match { - continue - } - } - filtered = append(filtered, s) - } - - return filtered -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go deleted file mode 100644 index 6d382ba2b..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -// PortForward prepares a streaming endpoint to forward ports from a PodSandbox, and returns the address. -func (c *criService) PortForward(ctx context.Context, r *runtime.PortForwardRequest) (retRes *runtime.PortForwardResponse, retErr error) { - sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId()) - if err != nil { - return nil, errors.Wrapf(err, "failed to find sandbox %q", r.GetPodSandboxId()) - } - if sandbox.Status.Get().State != sandboxstore.StateReady { - return nil, errors.New("sandbox container is not running") - } - // TODO(random-liu): Verify that ports are exposed. - return c.streamServer.GetPortForward(r) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_unix.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_unix.go deleted file mode 100644 index 5691c2b61..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_unix.go +++ /dev/null @@ -1,128 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "fmt" - "io" - "net" - "time" - - "github.com/containerd/containerd/log" - "github.com/containernetworking/plugins/pkg/ns" - "github.com/pkg/errors" - "golang.org/x/net/context" - - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// portForward uses netns to enter the sandbox namespace, and forwards a stream inside the -// the namespace to a specific port. It keeps forwarding until it exits or client disconnect. -func (c *criService) portForward(ctx context.Context, id string, port int32, stream io.ReadWriteCloser) error { - s, err := c.sandboxStore.Get(id) - if err != nil { - return errors.Wrapf(err, "failed to find sandbox %q in store", id) - } - - var netNSDo func(func(ns.NetNS) error) error - // netNSPath is the network namespace path for logging. - var netNSPath string - securityContext := s.Config.GetLinux().GetSecurityContext() - hostNet := securityContext.GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE - if !hostNet { - if closed, err := s.NetNS.Closed(); err != nil { - return errors.Wrapf(err, "failed to check netwok namespace closed for sandbox %q", id) - } else if closed { - return errors.Errorf("network namespace for sandbox %q is closed", id) - } - netNSDo = s.NetNS.Do - netNSPath = s.NetNS.GetPath() - } else { - // Run the function directly for host network. - netNSDo = func(do func(_ ns.NetNS) error) error { - return do(nil) - } - netNSPath = "host" - } - - log.G(ctx).Infof("Executing port forwarding in network namespace %q", netNSPath) - err = netNSDo(func(_ ns.NetNS) error { - defer stream.Close() - // TODO: hardcoded to tcp4 because localhost resolves to ::1 by default if the system has IPv6 enabled. - // Theoretically happy eyeballs will try IPv6 first and fallback to IPv4 - // but resolving localhost doesn't seem to return and IPv4 address, thus failing the connection. - conn, err := net.Dial("tcp4", fmt.Sprintf("localhost:%d", port)) - if err != nil { - return errors.Wrapf(err, "failed to dial %d", port) - } - defer conn.Close() - - errCh := make(chan error, 2) - // Copy from the the namespace port connection to the client stream - go func() { - log.G(ctx).Debugf("PortForward copying data from namespace %q port %d to the client stream", id, port) - _, err := io.Copy(stream, conn) - errCh <- err - }() - - // Copy from the client stream to the namespace port connection - go func() { - log.G(ctx).Debugf("PortForward copying data from client stream to namespace %q port %d", id, port) - _, err := io.Copy(conn, stream) - errCh <- err - }() - - // Wait until the first error is returned by one of the connections - // we use errFwd to store the result of the port forwarding operation - // if the context is cancelled close everything and return - var errFwd error - select { - case errFwd = <-errCh: - log.G(ctx).Debugf("PortForward stop forwarding in one direction in network namespace %q port %d: %v", id, port, errFwd) - case <-ctx.Done(): - log.G(ctx).Debugf("PortForward cancelled in network namespace %q port %d: %v", id, port, ctx.Err()) - return ctx.Err() - } - // give a chance to terminate gracefully or timeout - // after 1s - // https://linux.die.net/man/1/socat - const timeout = time.Second - select { - case e := <-errCh: - if errFwd == nil { - errFwd = e - } - log.G(ctx).Debugf("PortForward stopped forwarding in both directions in network namespace %q port %d: %v", id, port, e) - case <-time.After(timeout): - log.G(ctx).Debugf("PortForward timed out waiting to close the connection in network namespace %q port %d", id, port) - case <-ctx.Done(): - log.G(ctx).Debugf("PortForward cancelled in network namespace %q port %d: %v", id, port, ctx.Err()) - errFwd = ctx.Err() - } - - return errFwd - }) - - if err != nil { - return errors.Wrapf(err, "failed to execute portforward in network namespace %q", netNSPath) - } - log.G(ctx).Infof("Finish port forwarding for %q port %d", id, port) - - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_windows.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_windows.go deleted file mode 100644 index 3c328a314..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_windows.go +++ /dev/null @@ -1,80 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "bytes" - "fmt" - "io" - - "github.com/pkg/errors" - "golang.org/x/net/context" - "k8s.io/utils/exec" - - "github.com/containerd/cri/pkg/ioutil" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -func (c *criService) portForward(ctx context.Context, id string, port int32, stream io.ReadWriter) error { - stdout := ioutil.NewNopWriteCloser(stream) - stderrBuffer := new(bytes.Buffer) - stderr := ioutil.NewNopWriteCloser(stderrBuffer) - // localhost is resolved to 127.0.0.1 in ipv4, and ::1 in ipv6. - // Explicitly using ipv4 IP address in here to avoid flakiness. - cmd := []string{"wincat.exe", "127.0.0.1", fmt.Sprint(port)} - err := c.execInSandbox(ctx, id, cmd, stream, stdout, stderr) - if err != nil { - return errors.Wrapf(err, "failed to execute port forward in sandbox: %s", stderrBuffer.String()) - } - return nil -} - -func (c *criService) execInSandbox(ctx context.Context, sandboxID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser) error { - // Get sandbox from our sandbox store. - sb, err := c.sandboxStore.Get(sandboxID) - if err != nil { - return errors.Wrapf(err, "failed to find sandbox %q in store", sandboxID) - } - - // Check the sandbox state - state := sb.Status.Get().State - if state != sandboxstore.StateReady { - return errors.Errorf("sandbox is in %s state", fmt.Sprint(state)) - } - - opts := execOptions{ - cmd: cmd, - stdin: stdin, - stdout: stdout, - stderr: stderr, - tty: false, - resize: nil, - } - exitCode, err := c.execInternal(ctx, sb.Container, sandboxID, opts) - if err != nil { - return errors.Wrap(err, "failed to exec in sandbox") - } - if *exitCode == 0 { - return nil - } - return &exec.CodeExitError{ - Err: errors.Errorf("error executing command %v, exit code %d", cmd, *exitCode), - Code: int(*exitCode), - } -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_remove.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_remove.go deleted file mode 100644 index 2c2deb2e0..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_remove.go +++ /dev/null @@ -1,115 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/store" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -// RemovePodSandbox removes the sandbox. If there are running containers in the -// sandbox, they should be forcibly removed. -func (c *criService) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodSandboxRequest) (*runtime.RemovePodSandboxResponse, error) { - sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId()) - if err != nil { - if err != store.ErrNotExist { - return nil, errors.Wrapf(err, "an error occurred when try to find sandbox %q", - r.GetPodSandboxId()) - } - // Do not return error if the id doesn't exist. - log.G(ctx).Tracef("RemovePodSandbox called for sandbox %q that does not exist", - r.GetPodSandboxId()) - return &runtime.RemovePodSandboxResponse{}, nil - } - // Use the full sandbox id. - id := sandbox.ID - - // Return error if sandbox container is still running or unknown. - state := sandbox.Status.Get().State - if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown { - logrus.Infof("Forcibly stopping sandbox %q", id) - if err := c.stopPodSandbox(ctx, sandbox); err != nil { - return nil, errors.Wrapf(err, "failed to forcibly stop sandbox %q", id) - } - } - - // Return error if sandbox network namespace is not closed yet. - if sandbox.NetNS != nil { - nsPath := sandbox.NetNS.GetPath() - if closed, err := sandbox.NetNS.Closed(); err != nil { - return nil, errors.Wrapf(err, "failed to check sandbox network namespace %q closed", nsPath) - } else if !closed { - return nil, errors.Errorf("sandbox network namespace %q is not fully closed", nsPath) - } - } - - // Remove all containers inside the sandbox. - // NOTE(random-liu): container could still be created after this point, Kubelet should - // not rely on this behavior. - // TODO(random-liu): Introduce an intermediate state to avoid container creation after - // this point. - cntrs := c.containerStore.List() - for _, cntr := range cntrs { - if cntr.SandboxID != id { - continue - } - _, err = c.RemoveContainer(ctx, &runtime.RemoveContainerRequest{ContainerId: cntr.ID}) - if err != nil { - return nil, errors.Wrapf(err, "failed to remove container %q", cntr.ID) - } - } - - // Cleanup the sandbox root directories. - sandboxRootDir := c.getSandboxRootDir(id) - if err := ensureRemoveAll(ctx, sandboxRootDir); err != nil { - return nil, errors.Wrapf(err, "failed to remove sandbox root directory %q", - sandboxRootDir) - } - volatileSandboxRootDir := c.getVolatileSandboxRootDir(id) - if err := ensureRemoveAll(ctx, volatileSandboxRootDir); err != nil { - return nil, errors.Wrapf(err, "failed to remove volatile sandbox root directory %q", - volatileSandboxRootDir) - } - - // Delete sandbox container. - if err := sandbox.Container.Delete(ctx, containerd.WithSnapshotCleanup); err != nil { - if !errdefs.IsNotFound(err) { - return nil, errors.Wrapf(err, "failed to delete sandbox container %q", id) - } - log.G(ctx).Tracef("Remove called for sandbox container %q that does not exist", id) - } - - // Remove sandbox from sandbox store. Note that once the sandbox is successfully - // deleted: - // 1) ListPodSandbox will not include this sandbox. - // 2) PodSandboxStatus and StopPodSandbox will return error. - // 3) On-going operations which have held the reference will not be affected. - c.sandboxStore.Delete(id) - - // Release the sandbox name reserved for the sandbox. - c.sandboxNameIndex.ReleaseByKey(id) - - return &runtime.RemovePodSandboxResponse{}, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go deleted file mode 100644 index e0b207d7a..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go +++ /dev/null @@ -1,548 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "encoding/json" - "math" - goruntime "runtime" - "strings" - - "github.com/containerd/containerd" - containerdio "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - cni "github.com/containerd/go-cni" - "github.com/containerd/nri" - v1 "github.com/containerd/nri/types/v1" - "github.com/containerd/typeurl" - "github.com/davecgh/go-spew/spew" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/annotations" - criconfig "github.com/containerd/cri/pkg/config" - customopts "github.com/containerd/cri/pkg/containerd/opts" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/netns" - "github.com/containerd/cri/pkg/server/bandwidth" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" - "github.com/containerd/cri/pkg/util" - selinux "github.com/opencontainers/selinux/go-selinux" -) - -func init() { - typeurl.Register(&sandboxstore.Metadata{}, - "github.com/containerd/cri/pkg/store/sandbox", "Metadata") -} - -// RunPodSandbox creates and starts a pod-level sandbox. Runtimes should ensure -// the sandbox is in ready state. -func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandboxRequest) (_ *runtime.RunPodSandboxResponse, retErr error) { - config := r.GetConfig() - log.G(ctx).Debugf("Sandbox config %+v", config) - - // Generate unique id and name for the sandbox and reserve the name. - id := util.GenerateID() - metadata := config.GetMetadata() - if metadata == nil { - return nil, errors.New("sandbox config must include metadata") - } - name := makeSandboxName(metadata) - log.G(ctx).Debugf("Generated id %q for sandbox %q", id, name) - // Reserve the sandbox name to avoid concurrent `RunPodSandbox` request starting the - // same sandbox. - if err := c.sandboxNameIndex.Reserve(name, id); err != nil { - return nil, errors.Wrapf(err, "failed to reserve sandbox name %q", name) - } - defer func() { - // Release the name if the function returns with an error. - if retErr != nil { - c.sandboxNameIndex.ReleaseByName(name) - } - }() - - // Create initial internal sandbox object. - sandbox := sandboxstore.NewSandbox( - sandboxstore.Metadata{ - ID: id, - Name: name, - Config: config, - RuntimeHandler: r.GetRuntimeHandler(), - }, - sandboxstore.Status{ - State: sandboxstore.StateUnknown, - }, - ) - - // Ensure sandbox container image snapshot. - image, err := c.ensureImageExists(ctx, c.config.SandboxImage, config) - if err != nil { - return nil, errors.Wrapf(err, "failed to get sandbox image %q", c.config.SandboxImage) - } - containerdImage, err := c.toContainerdImage(ctx, *image) - if err != nil { - return nil, errors.Wrapf(err, "failed to get image from containerd %q", image.ID) - } - - ociRuntime, err := c.getSandboxRuntime(config, r.GetRuntimeHandler()) - if err != nil { - return nil, errors.Wrap(err, "failed to get sandbox runtime") - } - log.G(ctx).Debugf("Use OCI %+v for sandbox %q", ociRuntime, id) - - podNetwork := true - // Pod network is always needed on windows. - if goruntime.GOOS != "windows" && - config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { - // Pod network is not needed on linux with host network. - podNetwork = false - } - if podNetwork { - // If it is not in host network namespace then create a namespace and set the sandbox - // handle. NetNSPath in sandbox metadata and NetNS is non empty only for non host network - // namespaces. If the pod is in host network namespace then both are empty and should not - // be used. - sandbox.NetNS, err = netns.NewNetNS() - if err != nil { - return nil, errors.Wrapf(err, "failed to create network namespace for sandbox %q", id) - } - sandbox.NetNSPath = sandbox.NetNS.GetPath() - defer func() { - if retErr != nil { - // Teardown network if an error is returned. - if err := c.teardownPodNetwork(ctx, sandbox); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to destroy network for sandbox %q", id) - } - - if err := sandbox.NetNS.Remove(); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to remove network namespace %s for sandbox %q", sandbox.NetNSPath, id) - } - sandbox.NetNSPath = "" - } - }() - - // Setup network for sandbox. - // Certain VM based solutions like clear containers (Issue containerd/cri-containerd#524) - // rely on the assumption that CRI shim will not be querying the network namespace to check the - // network states such as IP. - // In future runtime implementation should avoid relying on CRI shim implementation details. - // In this case however caching the IP will add a subtle performance enhancement by avoiding - // calls to network namespace of the pod to query the IP of the veth interface on every - // SandboxStatus request. - if err := c.setupPodNetwork(ctx, &sandbox); err != nil { - return nil, errors.Wrapf(err, "failed to setup network for sandbox %q", id) - } - } - - // Create sandbox container. - // NOTE: sandboxContainerSpec SHOULD NOT have side - // effect, e.g. accessing/creating files, so that we can test - // it safely. - spec, err := c.sandboxContainerSpec(id, config, &image.ImageSpec.Config, sandbox.NetNSPath, ociRuntime.PodAnnotations) - if err != nil { - return nil, errors.Wrap(err, "failed to generate sandbox container spec") - } - log.G(ctx).Debugf("Sandbox container %q spec: %#+v", id, spew.NewFormatter(spec)) - sandbox.ProcessLabel = spec.Process.SelinuxLabel - defer func() { - if retErr != nil { - selinux.ReleaseLabel(sandbox.ProcessLabel) - } - }() - - // handle any KVM based runtime - if err := modifyProcessLabel(ociRuntime.Type, spec); err != nil { - return nil, err - } - - if config.GetLinux().GetSecurityContext().GetPrivileged() { - // If privileged don't set selinux label, but we still record the MCS label so that - // the unused label can be freed later. - spec.Process.SelinuxLabel = "" - } - - // Generate spec options that will be applied to the spec later. - specOpts, err := c.sandboxContainerSpecOpts(config, &image.ImageSpec.Config) - if err != nil { - return nil, errors.Wrap(err, "failed to generate sanbdox container spec options") - } - - sandboxLabels := buildLabels(config.Labels, containerKindSandbox) - - runtimeOpts, err := generateRuntimeOptions(ociRuntime, c.config) - if err != nil { - return nil, errors.Wrap(err, "failed to generate runtime options") - } - opts := []containerd.NewContainerOpts{ - containerd.WithSnapshotter(c.config.ContainerdConfig.Snapshotter), - customopts.WithNewSnapshot(id, containerdImage), - containerd.WithSpec(spec, specOpts...), - containerd.WithContainerLabels(sandboxLabels), - containerd.WithContainerExtension(sandboxMetadataExtension, &sandbox.Metadata), - containerd.WithRuntime(ociRuntime.Type, runtimeOpts)} - - container, err := c.client.NewContainer(ctx, id, opts...) - if err != nil { - return nil, errors.Wrap(err, "failed to create containerd container") - } - defer func() { - if retErr != nil { - deferCtx, deferCancel := ctrdutil.DeferContext() - defer deferCancel() - if err := container.Delete(deferCtx, containerd.WithSnapshotCleanup); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to delete containerd container %q", id) - } - } - }() - - // Create sandbox container root directories. - sandboxRootDir := c.getSandboxRootDir(id) - if err := c.os.MkdirAll(sandboxRootDir, 0755); err != nil { - return nil, errors.Wrapf(err, "failed to create sandbox root directory %q", - sandboxRootDir) - } - defer func() { - if retErr != nil { - // Cleanup the sandbox root directory. - if err := c.os.RemoveAll(sandboxRootDir); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to remove sandbox root directory %q", - sandboxRootDir) - } - } - }() - volatileSandboxRootDir := c.getVolatileSandboxRootDir(id) - if err := c.os.MkdirAll(volatileSandboxRootDir, 0755); err != nil { - return nil, errors.Wrapf(err, "failed to create volatile sandbox root directory %q", - volatileSandboxRootDir) - } - defer func() { - if retErr != nil { - // Cleanup the volatile sandbox root directory. - if err := c.os.RemoveAll(volatileSandboxRootDir); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to remove volatile sandbox root directory %q", - volatileSandboxRootDir) - } - } - }() - - // Setup files required for the sandbox. - if err = c.setupSandboxFiles(id, config); err != nil { - return nil, errors.Wrapf(err, "failed to setup sandbox files") - } - defer func() { - if retErr != nil { - if err = c.cleanupSandboxFiles(id, config); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to cleanup sandbox files in %q", - sandboxRootDir) - } - } - }() - - // Update sandbox created timestamp. - info, err := container.Info(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get sandbox container info") - } - - // Create sandbox task in containerd. - log.G(ctx).Tracef("Create sandbox container (id=%q, name=%q).", - id, name) - - taskOpts := c.taskOpts(ociRuntime.Type) - // We don't need stdio for sandbox container. - task, err := container.NewTask(ctx, containerdio.NullIO, taskOpts...) - if err != nil { - return nil, errors.Wrap(err, "failed to create containerd task") - } - defer func() { - if retErr != nil { - deferCtx, deferCancel := ctrdutil.DeferContext() - defer deferCancel() - // Cleanup the sandbox container if an error is returned. - if _, err := task.Delete(deferCtx, WithNRISandboxDelete(id), containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - log.G(ctx).WithError(err).Errorf("Failed to delete sandbox container %q", id) - } - } - }() - - // wait is a long running background request, no timeout needed. - exitCh, err := task.Wait(ctrdutil.NamespacedContext()) - if err != nil { - return nil, errors.Wrap(err, "failed to wait for sandbox container task") - } - - nric, err := nri.New() - if err != nil { - return nil, errors.Wrap(err, "unable to create nri client") - } - if nric != nil { - nriSB := &nri.Sandbox{ - ID: id, - Labels: config.Labels, - } - if _, err := nric.InvokeWithSandbox(ctx, task, v1.Create, nriSB); err != nil { - return nil, errors.Wrap(err, "nri invoke") - } - } - - if err := task.Start(ctx); err != nil { - return nil, errors.Wrapf(err, "failed to start sandbox container task %q", id) - } - - if err := sandbox.Status.Update(func(status sandboxstore.Status) (sandboxstore.Status, error) { - // Set the pod sandbox as ready after successfully start sandbox container. - status.Pid = task.Pid() - status.State = sandboxstore.StateReady - status.CreatedAt = info.CreatedAt - return status, nil - }); err != nil { - return nil, errors.Wrap(err, "failed to update sandbox status") - } - - // Add sandbox into sandbox store in INIT state. - sandbox.Container = container - - if err := c.sandboxStore.Add(sandbox); err != nil { - return nil, errors.Wrapf(err, "failed to add sandbox %+v into store", sandbox) - } - - // start the monitor after adding sandbox into the store, this ensures - // that sandbox is in the store, when event monitor receives the TaskExit event. - // - // TaskOOM from containerd may come before sandbox is added to store, - // but we don't care about sandbox TaskOOM right now, so it is fine. - c.eventMonitor.startExitMonitor(context.Background(), id, task.Pid(), exitCh) - - return &runtime.RunPodSandboxResponse{PodSandboxId: id}, nil -} - -// setupPodNetwork setups up the network for a pod -func (c *criService) setupPodNetwork(ctx context.Context, sandbox *sandboxstore.Sandbox) error { - var ( - id = sandbox.ID - config = sandbox.Config - path = sandbox.NetNSPath - ) - if c.netPlugin == nil { - return errors.New("cni config not initialized") - } - - opts, err := cniNamespaceOpts(id, config) - if err != nil { - return errors.Wrap(err, "get cni namespace options") - } - - result, err := c.netPlugin.Setup(ctx, id, path, opts...) - if err != nil { - return err - } - logDebugCNIResult(ctx, id, result) - // Check if the default interface has IP config - if configs, ok := result.Interfaces[defaultIfName]; ok && len(configs.IPConfigs) > 0 { - sandbox.IP, sandbox.AdditionalIPs = selectPodIPs(configs.IPConfigs) - sandbox.CNIResult = result - return nil - } - return errors.Errorf("failed to find network info for sandbox %q", id) -} - -// cniNamespaceOpts get CNI namespace options from sandbox config. -func cniNamespaceOpts(id string, config *runtime.PodSandboxConfig) ([]cni.NamespaceOpts, error) { - opts := []cni.NamespaceOpts{ - cni.WithLabels(toCNILabels(id, config)), - } - - portMappings := toCNIPortMappings(config.GetPortMappings()) - if len(portMappings) > 0 { - opts = append(opts, cni.WithCapabilityPortMap(portMappings)) - } - - // Will return an error if the bandwidth limitation has the wrong unit - // or an unreasonable value see validateBandwidthIsReasonable() - bandWidth, err := toCNIBandWidth(config.Annotations) - if err != nil { - return nil, err - } - if bandWidth != nil { - opts = append(opts, cni.WithCapabilityBandWidth(*bandWidth)) - } - - dns := toCNIDNS(config.GetDnsConfig()) - if dns != nil { - opts = append(opts, cni.WithCapabilityDNS(*dns)) - } - - return opts, nil -} - -// toCNILabels adds pod metadata into CNI labels. -func toCNILabels(id string, config *runtime.PodSandboxConfig) map[string]string { - return map[string]string{ - "K8S_POD_NAMESPACE": config.GetMetadata().GetNamespace(), - "K8S_POD_NAME": config.GetMetadata().GetName(), - "K8S_POD_INFRA_CONTAINER_ID": id, - "IgnoreUnknown": "1", - } -} - -// toCNIBandWidth converts CRI annotations to CNI bandwidth. -func toCNIBandWidth(annotations map[string]string) (*cni.BandWidth, error) { - ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations) - if err != nil { - return nil, errors.Wrap(err, "reading pod bandwidth annotations") - } - - if ingress == nil && egress == nil { - return nil, nil - } - - bandWidth := &cni.BandWidth{} - - if ingress != nil { - bandWidth.IngressRate = uint64(ingress.Value()) - bandWidth.IngressBurst = math.MaxUint32 - } - - if egress != nil { - bandWidth.EgressRate = uint64(egress.Value()) - bandWidth.EgressBurst = math.MaxUint32 - } - - return bandWidth, nil -} - -// toCNIPortMappings converts CRI port mappings to CNI. -func toCNIPortMappings(criPortMappings []*runtime.PortMapping) []cni.PortMapping { - var portMappings []cni.PortMapping - for _, mapping := range criPortMappings { - if mapping.HostPort <= 0 { - continue - } - portMappings = append(portMappings, cni.PortMapping{ - HostPort: mapping.HostPort, - ContainerPort: mapping.ContainerPort, - Protocol: strings.ToLower(mapping.Protocol.String()), - HostIP: mapping.HostIp, - }) - } - return portMappings -} - -// toCNIDNS converts CRI DNSConfig to CNI. -func toCNIDNS(dns *runtime.DNSConfig) *cni.DNS { - if dns == nil { - return nil - } - return &cni.DNS{ - Servers: dns.GetServers(), - Searches: dns.GetSearches(), - Options: dns.GetOptions(), - } -} - -// selectPodIPs select an ip from the ip list. It prefers ipv4 more than ipv6 -// and returns the additional ips -// TODO(random-liu): Revisit the ip order in the ipv6 beta stage. (cri#1278) -func selectPodIPs(ipConfigs []*cni.IPConfig) (string, []string) { - var ( - additionalIPs []string - ip string - ) - for _, c := range ipConfigs { - if c.IP.To4() != nil && ip == "" { - ip = c.IP.String() - } else { - additionalIPs = append(additionalIPs, c.IP.String()) - } - } - if ip != "" { - return ip, additionalIPs - } - if len(ipConfigs) == 1 { - return additionalIPs[0], nil - } - return additionalIPs[0], additionalIPs[1:] -} - -// untrustedWorkload returns true if the sandbox contains untrusted workload. -func untrustedWorkload(config *runtime.PodSandboxConfig) bool { - return config.GetAnnotations()[annotations.UntrustedWorkload] == "true" -} - -// hostAccessingSandbox returns true if the sandbox configuration -// requires additional host access for the sandbox. -func hostAccessingSandbox(config *runtime.PodSandboxConfig) bool { - securityContext := config.GetLinux().GetSecurityContext() - - namespaceOptions := securityContext.GetNamespaceOptions() - if namespaceOptions.GetNetwork() == runtime.NamespaceMode_NODE || - namespaceOptions.GetPid() == runtime.NamespaceMode_NODE || - namespaceOptions.GetIpc() == runtime.NamespaceMode_NODE { - return true - } - - return false -} - -// getSandboxRuntime returns the runtime configuration for sandbox. -// If the sandbox contains untrusted workload, runtime for untrusted workload will be returned, -// or else default runtime will be returned. -func (c *criService) getSandboxRuntime(config *runtime.PodSandboxConfig, runtimeHandler string) (criconfig.Runtime, error) { - if untrustedWorkload(config) { - // If the untrusted annotation is provided, runtimeHandler MUST be empty. - if runtimeHandler != "" && runtimeHandler != criconfig.RuntimeUntrusted { - return criconfig.Runtime{}, errors.New("untrusted workload with explicit runtime handler is not allowed") - } - - // If the untrusted workload is requesting access to the host/node, this request will fail. - // - // Note: If the workload is marked untrusted but requests privileged, this can be granted, as the - // runtime may support this. For example, in a virtual-machine isolated runtime, privileged - // is a supported option, granting the workload to access the entire guest VM instead of host. - // TODO(windows): Deprecate this so that we don't need to handle it for windows. - if hostAccessingSandbox(config) { - return criconfig.Runtime{}, errors.New("untrusted workload with host access is not allowed") - } - - runtimeHandler = criconfig.RuntimeUntrusted - } - - if runtimeHandler == "" { - runtimeHandler = c.config.ContainerdConfig.DefaultRuntimeName - } - - handler, ok := c.config.ContainerdConfig.Runtimes[runtimeHandler] - if !ok { - return criconfig.Runtime{}, errors.Errorf("no runtime for %q is configured", runtimeHandler) - } - return handler, nil -} - -func logDebugCNIResult(ctx context.Context, sandboxID string, result *cni.CNIResult) { - if logrus.GetLevel() < logrus.DebugLevel { - return - } - cniResult, err := json.Marshal(result) - if err != nil { - log.G(ctx).WithError(err).Errorf("Failed to marshal CNI result for sandbox %q: %v", sandboxID, err) - return - } - log.G(ctx).Debugf("cni result for sandbox %q: %s", sandboxID, string(cniResult)) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_run_unix.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_run_unix.go deleted file mode 100644 index ad0b85254..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_run_unix.go +++ /dev/null @@ -1,310 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "fmt" - "os" - "strings" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/plugin" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - selinux "github.com/opencontainers/selinux/go-selinux" - "github.com/pkg/errors" - "golang.org/x/sys/unix" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/annotations" - customopts "github.com/containerd/cri/pkg/containerd/opts" - osinterface "github.com/containerd/cri/pkg/os" -) - -func (c *criService) sandboxContainerSpec(id string, config *runtime.PodSandboxConfig, - imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (_ *runtimespec.Spec, retErr error) { - // Creates a spec Generator with the default spec. - // TODO(random-liu): [P1] Compare the default settings with docker and containerd default. - specOpts := []oci.SpecOpts{ - customopts.WithoutRunMount, - customopts.WithoutDefaultSecuritySettings, - customopts.WithRelativeRoot(relativeRootfsPath), - oci.WithEnv(imageConfig.Env), - oci.WithRootFSReadonly(), - oci.WithHostname(config.GetHostname()), - } - if imageConfig.WorkingDir != "" { - specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir)) - } - - if len(imageConfig.Entrypoint) == 0 && len(imageConfig.Cmd) == 0 { - // Pause image must have entrypoint or cmd. - return nil, errors.Errorf("invalid empty entrypoint and cmd in image config %+v", imageConfig) - } - specOpts = append(specOpts, oci.WithProcessArgs(append(imageConfig.Entrypoint, imageConfig.Cmd...)...)) - - // Set cgroups parent. - if c.config.DisableCgroup { - specOpts = append(specOpts, customopts.WithDisabledCgroups) - } else { - if config.GetLinux().GetCgroupParent() != "" { - cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id) - specOpts = append(specOpts, oci.WithCgroup(cgroupsPath)) - } - } - - // When cgroup parent is not set, containerd-shim will create container in a child cgroup - // of the cgroup itself is in. - // TODO(random-liu): [P2] Set default cgroup path if cgroup parent is not specified. - - // Set namespace options. - var ( - securityContext = config.GetLinux().GetSecurityContext() - nsOptions = securityContext.GetNamespaceOptions() - ) - if nsOptions.GetNetwork() == runtime.NamespaceMode_NODE { - specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.NetworkNamespace)) - specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.UTSNamespace)) - } else { - specOpts = append(specOpts, oci.WithLinuxNamespace( - runtimespec.LinuxNamespace{ - Type: runtimespec.NetworkNamespace, - Path: nsPath, - })) - } - if nsOptions.GetPid() == runtime.NamespaceMode_NODE { - specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.PIDNamespace)) - } - if nsOptions.GetIpc() == runtime.NamespaceMode_NODE { - specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.IPCNamespace)) - } - - // It's fine to generate the spec before the sandbox /dev/shm - // is actually created. - sandboxDevShm := c.getSandboxDevShm(id) - if nsOptions.GetIpc() == runtime.NamespaceMode_NODE { - sandboxDevShm = devShm - } - specOpts = append(specOpts, oci.WithMounts([]runtimespec.Mount{ - { - Source: sandboxDevShm, - Destination: devShm, - Type: "bind", - Options: []string{"rbind", "ro"}, - }, - // Add resolv.conf for katacontainers to setup the DNS of pod VM properly. - { - Source: c.getResolvPath(id), - Destination: resolvConfPath, - Type: "bind", - Options: []string{"rbind", "ro"}, - }, - })) - - processLabel, mountLabel, err := initLabelsFromOpt(securityContext.GetSelinuxOptions()) - if err != nil { - return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions()) - } - defer func() { - if retErr != nil { - selinux.ReleaseLabel(processLabel) - } - }() - - supplementalGroups := securityContext.GetSupplementalGroups() - specOpts = append(specOpts, - customopts.WithSelinuxLabels(processLabel, mountLabel), - customopts.WithSupplementalGroups(supplementalGroups), - ) - - // Add sysctls - sysctls := config.GetLinux().GetSysctls() - specOpts = append(specOpts, customopts.WithSysctls(sysctls)) - - // Note: LinuxSandboxSecurityContext does not currently provide an apparmor profile - - if !c.config.DisableCgroup { - specOpts = append(specOpts, customopts.WithDefaultSandboxShares) - } - specOpts = append(specOpts, customopts.WithPodOOMScoreAdj(int(defaultSandboxOOMAdj), c.config.RestrictOOMScoreAdj)) - - for pKey, pValue := range getPassthroughAnnotations(config.Annotations, - runtimePodAnnotations) { - specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) - } - - specOpts = append(specOpts, - customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox), - customopts.WithAnnotation(annotations.SandboxID, id), - customopts.WithAnnotation(annotations.SandboxLogDir, config.GetLogDirectory()), - ) - - return c.runtimeSpec(id, "", specOpts...) -} - -// sandboxContainerSpecOpts generates OCI spec options for -// the sandbox container. -func (c *criService) sandboxContainerSpecOpts(config *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig) ([]oci.SpecOpts, error) { - var ( - securityContext = config.GetLinux().GetSecurityContext() - specOpts []oci.SpecOpts - ) - seccompSpecOpts, err := c.generateSeccompSpecOpts( - securityContext.GetSeccompProfilePath(), - securityContext.GetPrivileged(), - c.seccompEnabled()) - if err != nil { - return nil, errors.Wrap(err, "failed to generate seccomp spec opts") - } - if seccompSpecOpts != nil { - specOpts = append(specOpts, seccompSpecOpts) - } - - userstr, err := generateUserString( - "", - securityContext.GetRunAsUser(), - securityContext.GetRunAsGroup(), - ) - if err != nil { - return nil, errors.Wrap(err, "failed to generate user string") - } - if userstr == "" { - // Lastly, since no user override was passed via CRI try to set via OCI - // Image - userstr = imageConfig.User - } - if userstr != "" { - specOpts = append(specOpts, oci.WithUser(userstr)) - } - return specOpts, nil -} - -// setupSandboxFiles sets up necessary sandbox files including /dev/shm, /etc/hosts, -// /etc/resolv.conf and /etc/hostname. -func (c *criService) setupSandboxFiles(id string, config *runtime.PodSandboxConfig) error { - sandboxEtcHostname := c.getSandboxHostname(id) - hostname := config.GetHostname() - if hostname == "" { - var err error - hostname, err = c.os.Hostname() - if err != nil { - return errors.Wrap(err, "failed to get hostname") - } - } - if err := c.os.WriteFile(sandboxEtcHostname, []byte(hostname+"\n"), 0644); err != nil { - return errors.Wrapf(err, "failed to write hostname to %q", sandboxEtcHostname) - } - - // TODO(random-liu): Consider whether we should maintain /etc/hosts and /etc/resolv.conf in kubelet. - sandboxEtcHosts := c.getSandboxHosts(id) - if err := c.os.CopyFile(etcHosts, sandboxEtcHosts, 0644); err != nil { - return errors.Wrapf(err, "failed to generate sandbox hosts file %q", sandboxEtcHosts) - } - - // Set DNS options. Maintain a resolv.conf for the sandbox. - var err error - resolvContent := "" - if dnsConfig := config.GetDnsConfig(); dnsConfig != nil { - resolvContent, err = parseDNSOptions(dnsConfig.Servers, dnsConfig.Searches, dnsConfig.Options) - if err != nil { - return errors.Wrapf(err, "failed to parse sandbox DNSConfig %+v", dnsConfig) - } - } - resolvPath := c.getResolvPath(id) - if resolvContent == "" { - // copy host's resolv.conf to resolvPath - err = c.os.CopyFile(resolvConfPath, resolvPath, 0644) - if err != nil { - return errors.Wrapf(err, "failed to copy host's resolv.conf to %q", resolvPath) - } - } else { - err = c.os.WriteFile(resolvPath, []byte(resolvContent), 0644) - if err != nil { - return errors.Wrapf(err, "failed to write resolv content to %q", resolvPath) - } - } - - // Setup sandbox /dev/shm. - if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetIpc() == runtime.NamespaceMode_NODE { - if _, err := c.os.Stat(devShm); err != nil { - return errors.Wrapf(err, "host %q is not available for host ipc", devShm) - } - } else { - sandboxDevShm := c.getSandboxDevShm(id) - if err := c.os.MkdirAll(sandboxDevShm, 0700); err != nil { - return errors.Wrap(err, "failed to create sandbox shm") - } - shmproperty := fmt.Sprintf("mode=1777,size=%d", defaultShmSize) - if err := c.os.(osinterface.UNIX).Mount("shm", sandboxDevShm, "tmpfs", uintptr(unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV), shmproperty); err != nil { - return errors.Wrap(err, "failed to mount sandbox shm") - } - } - - return nil -} - -// parseDNSOptions parse DNS options into resolv.conf format content, -// if none option is specified, will return empty with no error. -func parseDNSOptions(servers, searches, options []string) (string, error) { - resolvContent := "" - - if len(searches) > maxDNSSearches { - return "", errors.Errorf("DNSOption.Searches has more than %d domains", maxDNSSearches) - } - - if len(searches) > 0 { - resolvContent += fmt.Sprintf("search %s\n", strings.Join(searches, " ")) - } - - if len(servers) > 0 { - resolvContent += fmt.Sprintf("nameserver %s\n", strings.Join(servers, "\nnameserver ")) - } - - if len(options) > 0 { - resolvContent += fmt.Sprintf("options %s\n", strings.Join(options, " ")) - } - - return resolvContent, nil -} - -// cleanupSandboxFiles unmount some sandbox files, we rely on the removal of sandbox root directory to -// remove these files. Unmount should *NOT* return error if the mount point is already unmounted. -func (c *criService) cleanupSandboxFiles(id string, config *runtime.PodSandboxConfig) error { - if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetIpc() != runtime.NamespaceMode_NODE { - path, err := c.os.FollowSymlinkInScope(c.getSandboxDevShm(id), "/") - if err != nil { - return errors.Wrap(err, "failed to follow symlink") - } - if err := c.os.(osinterface.UNIX).Unmount(path); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "failed to unmount %q", path) - } - } - return nil -} - -// taskOpts generates task options for a (sandbox) container. -func (c *criService) taskOpts(runtimeType string) []containerd.NewTaskOpts { - // TODO(random-liu): Remove this after shim v1 is deprecated. - var taskOpts []containerd.NewTaskOpts - if c.config.NoPivot && (runtimeType == plugin.RuntimeRuncV1 || runtimeType == plugin.RuntimeRuncV2) { - taskOpts = append(taskOpts, containerd.WithNoPivotRoot) - } - return taskOpts -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_run_windows.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_run_windows.go deleted file mode 100644 index 85105c299..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_run_windows.go +++ /dev/null @@ -1,91 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/annotations" - customopts "github.com/containerd/cri/pkg/containerd/opts" -) - -func (c *criService) sandboxContainerSpec(id string, config *runtime.PodSandboxConfig, - imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (*runtimespec.Spec, error) { - // Creates a spec Generator with the default spec. - specOpts := []oci.SpecOpts{ - oci.WithEnv(imageConfig.Env), - oci.WithHostname(config.GetHostname()), - } - if imageConfig.WorkingDir != "" { - specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir)) - } - - if len(imageConfig.Entrypoint) == 0 && len(imageConfig.Cmd) == 0 { - // Pause image must have entrypoint or cmd. - return nil, errors.Errorf("invalid empty entrypoint and cmd in image config %+v", imageConfig) - } - specOpts = append(specOpts, oci.WithProcessArgs(append(imageConfig.Entrypoint, imageConfig.Cmd...)...)) - - specOpts = append(specOpts, - // Clear the root location since hcsshim expects it. - // NOTE: readonly rootfs doesn't work on windows. - customopts.WithoutRoot, - customopts.WithWindowsNetworkNamespace(nsPath), - ) - - specOpts = append(specOpts, customopts.WithWindowsDefaultSandboxShares) - - for pKey, pValue := range getPassthroughAnnotations(config.Annotations, - runtimePodAnnotations) { - specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) - } - - specOpts = append(specOpts, - customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox), - customopts.WithAnnotation(annotations.SandboxID, id), - customopts.WithAnnotation(annotations.SandboxLogDir, config.GetLogDirectory()), - ) - - return c.runtimeSpec(id, "", specOpts...) -} - -// No sandbox container spec options for windows yet. -func (c *criService) sandboxContainerSpecOpts(config *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig) ([]oci.SpecOpts, error) { - return nil, nil -} - -// No sandbox files needed for windows. -func (c *criService) setupSandboxFiles(id string, config *runtime.PodSandboxConfig) error { - return nil -} - -// No sandbox files needed for windows. -func (c *criService) cleanupSandboxFiles(id string, config *runtime.PodSandboxConfig) error { - return nil -} - -// No task options needed for windows. -func (c *criService) taskOpts(runtimeType string) []containerd.NewTaskOpts { - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_status.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_status.go deleted file mode 100644 index 5644ab1be..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_status.go +++ /dev/null @@ -1,217 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "encoding/json" - goruntime "runtime" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" - cni "github.com/containerd/go-cni" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -// PodSandboxStatus returns the status of the PodSandbox. -func (c *criService) PodSandboxStatus(ctx context.Context, r *runtime.PodSandboxStatusRequest) (*runtime.PodSandboxStatusResponse, error) { - sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId()) - if err != nil { - return nil, errors.Wrap(err, "an error occurred when try to find sandbox") - } - - ip, additionalIPs, err := c.getIPs(sandbox) - if err != nil { - return nil, errors.Wrap(err, "failed to get sandbox ip") - } - status := toCRISandboxStatus(sandbox.Metadata, sandbox.Status.Get(), ip, additionalIPs) - if status.GetCreatedAt() == 0 { - // CRI doesn't allow CreatedAt == 0. - info, err := sandbox.Container.Info(ctx) - if err != nil { - return nil, errors.Wrapf(err, "failed to get CreatedAt for sandbox container in %q state", status.State) - } - status.CreatedAt = info.CreatedAt.UnixNano() - } - if !r.GetVerbose() { - return &runtime.PodSandboxStatusResponse{Status: status}, nil - } - - // Generate verbose information. - info, err := toCRISandboxInfo(ctx, sandbox) - if err != nil { - return nil, errors.Wrap(err, "failed to get verbose sandbox container info") - } - - return &runtime.PodSandboxStatusResponse{ - Status: status, - Info: info, - }, nil -} - -func (c *criService) getIPs(sandbox sandboxstore.Sandbox) (string, []string, error) { - config := sandbox.Config - - if goruntime.GOOS != "windows" && - config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { - // For sandboxes using the node network we are not - // responsible for reporting the IP. - return "", nil, nil - } - - if closed, err := sandbox.NetNS.Closed(); err != nil { - return "", nil, errors.Wrap(err, "check network namespace closed") - } else if closed { - return "", nil, nil - } - - return sandbox.IP, sandbox.AdditionalIPs, nil -} - -// toCRISandboxStatus converts sandbox metadata into CRI pod sandbox status. -func toCRISandboxStatus(meta sandboxstore.Metadata, status sandboxstore.Status, ip string, additionalIPs []string) *runtime.PodSandboxStatus { - // Set sandbox state to NOTREADY by default. - state := runtime.PodSandboxState_SANDBOX_NOTREADY - if status.State == sandboxstore.StateReady { - state = runtime.PodSandboxState_SANDBOX_READY - } - nsOpts := meta.Config.GetLinux().GetSecurityContext().GetNamespaceOptions() - var ips []*runtime.PodIP - for _, additionalIP := range additionalIPs { - ips = append(ips, &runtime.PodIP{Ip: additionalIP}) - } - return &runtime.PodSandboxStatus{ - Id: meta.ID, - Metadata: meta.Config.GetMetadata(), - State: state, - CreatedAt: status.CreatedAt.UnixNano(), - Network: &runtime.PodSandboxNetworkStatus{ - Ip: ip, - AdditionalIps: ips, - }, - Linux: &runtime.LinuxPodSandboxStatus{ - Namespaces: &runtime.Namespace{ - Options: &runtime.NamespaceOption{ - Network: nsOpts.GetNetwork(), - Pid: nsOpts.GetPid(), - Ipc: nsOpts.GetIpc(), - }, - }, - }, - Labels: meta.Config.GetLabels(), - Annotations: meta.Config.GetAnnotations(), - RuntimeHandler: meta.RuntimeHandler, - } -} - -// SandboxInfo is extra information for sandbox. -// TODO (mikebrow): discuss predefining constants structures for some or all of these field names in CRI -type SandboxInfo struct { - Pid uint32 `json:"pid"` - Status string `json:"processStatus"` - NetNSClosed bool `json:"netNamespaceClosed"` - Image string `json:"image"` - SnapshotKey string `json:"snapshotKey"` - Snapshotter string `json:"snapshotter"` - // Note: a new field `RuntimeHandler` has been added into the CRI PodSandboxStatus struct, and - // should be set. This `RuntimeHandler` field will be deprecated after containerd 1.3 (tracked - // in https://github.com/containerd/cri/issues/1064). - RuntimeHandler string `json:"runtimeHandler"` // see the Note above - RuntimeType string `json:"runtimeType"` - RuntimeOptions interface{} `json:"runtimeOptions"` - Config *runtime.PodSandboxConfig `json:"config"` - RuntimeSpec *runtimespec.Spec `json:"runtimeSpec"` - CNIResult *cni.CNIResult `json:"cniResult"` -} - -// toCRISandboxInfo converts internal container object information to CRI sandbox status response info map. -func toCRISandboxInfo(ctx context.Context, sandbox sandboxstore.Sandbox) (map[string]string, error) { - container := sandbox.Container - task, err := container.Task(ctx, nil) - if err != nil && !errdefs.IsNotFound(err) { - return nil, errors.Wrap(err, "failed to get sandbox container task") - } - - var processStatus containerd.ProcessStatus - if task != nil { - taskStatus, err := task.Status(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get task status") - } - - processStatus = taskStatus.Status - } - - si := &SandboxInfo{ - Pid: sandbox.Status.Get().Pid, - RuntimeHandler: sandbox.RuntimeHandler, - Status: string(processStatus), - Config: sandbox.Config, - CNIResult: sandbox.CNIResult, - } - - if si.Status == "" { - // If processStatus is empty, it means that the task is deleted. Apply "deleted" - // status which does not exist in containerd. - si.Status = "deleted" - } - - if sandbox.NetNS != nil { - // Add network closed information if sandbox is not using host network. - closed, err := sandbox.NetNS.Closed() - if err != nil { - return nil, errors.Wrap(err, "failed to check network namespace closed") - } - si.NetNSClosed = closed - } - - spec, err := container.Spec(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get sandbox container runtime spec") - } - si.RuntimeSpec = spec - - ctrInfo, err := container.Info(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get sandbox container info") - } - // Do not use config.SandboxImage because the configuration might - // be changed during restart. It may not reflect the actual image - // used by the sandbox container. - si.Image = ctrInfo.Image - si.SnapshotKey = ctrInfo.SnapshotKey - si.Snapshotter = ctrInfo.Snapshotter - - runtimeOptions, err := getRuntimeOptions(ctrInfo) - if err != nil { - return nil, errors.Wrap(err, "failed to get runtime options") - } - si.RuntimeType = ctrInfo.Runtime.Name - si.RuntimeOptions = runtimeOptions - - infoBytes, err := json.Marshal(si) - if err != nil { - return nil, errors.Wrapf(err, "failed to marshal info %v", si) - } - return map[string]string{ - "info": string(infoBytes), - }, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go deleted file mode 100644 index 9b6e0a6ec..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go +++ /dev/null @@ -1,195 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "syscall" - "time" - - eventtypes "github.com/containerd/containerd/api/events" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" -) - -// StopPodSandbox stops the sandbox. If there are any running containers in the -// sandbox, they should be forcibly terminated. -func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandboxRequest) (*runtime.StopPodSandboxResponse, error) { - sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId()) - if err != nil { - return nil, errors.Wrapf(err, "an error occurred when try to find sandbox %q", - r.GetPodSandboxId()) - } - - if err := c.stopPodSandbox(ctx, sandbox); err != nil { - return nil, err - } - - return &runtime.StopPodSandboxResponse{}, nil -} - -func (c *criService) stopPodSandbox(ctx context.Context, sandbox sandboxstore.Sandbox) error { - // Use the full sandbox id. - id := sandbox.ID - - // Stop all containers inside the sandbox. This terminates the container forcibly, - // and container may still be created, so production should not rely on this behavior. - // TODO(random-liu): Introduce a state in sandbox to avoid future container creation. - containers := c.containerStore.List() - for _, container := range containers { - if container.SandboxID != id { - continue - } - // Forcibly stop the container. Do not use `StopContainer`, because it introduces a race - // if a container is removed after list. - if err := c.stopContainer(ctx, container, 0); err != nil { - return errors.Wrapf(err, "failed to stop container %q", container.ID) - } - } - - if err := c.cleanupSandboxFiles(id, sandbox.Config); err != nil { - return errors.Wrap(err, "failed to cleanup sandbox files") - } - - // Only stop sandbox container when it's running or unknown. - state := sandbox.Status.Get().State - if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown { - if err := c.stopSandboxContainer(ctx, sandbox); err != nil { - return errors.Wrapf(err, "failed to stop sandbox container %q in %q state", id, state) - } - } - - // Teardown network for sandbox. - if sandbox.NetNS != nil { - // Use empty netns path if netns is not available. This is defined in: - // https://github.com/containernetworking/cni/blob/v0.7.0-alpha1/SPEC.md - if closed, err := sandbox.NetNS.Closed(); err != nil { - return errors.Wrap(err, "failed to check network namespace closed") - } else if closed { - sandbox.NetNSPath = "" - } - if err := c.teardownPodNetwork(ctx, sandbox); err != nil { - return errors.Wrapf(err, "failed to destroy network for sandbox %q", id) - } - if err := sandbox.NetNS.Remove(); err != nil { - return errors.Wrapf(err, "failed to remove network namespace for sandbox %q", id) - } - } - - log.G(ctx).Infof("TearDown network for sandbox %q successfully", id) - - return nil -} - -// stopSandboxContainer kills the sandbox container. -// `task.Delete` is not called here because it will be called when -// the event monitor handles the `TaskExit` event. -func (c *criService) stopSandboxContainer(ctx context.Context, sandbox sandboxstore.Sandbox) error { - id := sandbox.ID - container := sandbox.Container - state := sandbox.Status.Get().State - task, err := container.Task(ctx, nil) - if err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to get sandbox container") - } - // Don't return for unknown state, some cleanup needs to be done. - if state == sandboxstore.StateUnknown { - return cleanupUnknownSandbox(ctx, id, sandbox) - } - return nil - } - - // Handle unknown state. - // The cleanup logic is the same with container unknown state. - if state == sandboxstore.StateUnknown { - // Start an exit handler for containers in unknown state. - waitCtx, waitCancel := context.WithCancel(ctrdutil.NamespacedContext()) - defer waitCancel() - exitCh, err := task.Wait(waitCtx) - if err != nil { - if !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to wait for task") - } - return cleanupUnknownSandbox(ctx, id, sandbox) - } - - exitCtx, exitCancel := context.WithCancel(context.Background()) - stopCh := c.eventMonitor.startExitMonitor(exitCtx, id, task.Pid(), exitCh) - defer func() { - exitCancel() - // This ensures that exit monitor is stopped before - // `Wait` is cancelled, so no exit event is generated - // because of the `Wait` cancellation. - <-stopCh - }() - } - - // Kill the sandbox container. - if err = task.Kill(ctx, syscall.SIGKILL); err != nil && !errdefs.IsNotFound(err) { - return errors.Wrap(err, "failed to kill sandbox container") - } - - return c.waitSandboxStop(ctx, sandbox) -} - -// waitSandboxStop waits for sandbox to be stopped until context is cancelled or -// the context deadline is exceeded. -func (c *criService) waitSandboxStop(ctx context.Context, sandbox sandboxstore.Sandbox) error { - select { - case <-ctx.Done(): - return errors.Wrapf(ctx.Err(), "wait sandbox container %q", sandbox.ID) - case <-sandbox.Stopped(): - return nil - } -} - -// teardownPodNetwork removes the network from the pod -func (c *criService) teardownPodNetwork(ctx context.Context, sandbox sandboxstore.Sandbox) error { - if c.netPlugin == nil { - return errors.New("cni config not initialized") - } - - var ( - id = sandbox.ID - path = sandbox.NetNSPath - config = sandbox.Config - ) - opts, err := cniNamespaceOpts(id, config) - if err != nil { - return errors.Wrap(err, "get cni namespace options") - } - - return c.netPlugin.Remove(ctx, id, path, opts...) -} - -// cleanupUnknownSandbox cleanup stopped sandbox in unknown state. -func cleanupUnknownSandbox(ctx context.Context, id string, sandbox sandboxstore.Sandbox) error { - // Reuse handleSandboxExit to do the cleanup. - return handleSandboxExit(ctx, &eventtypes.TaskExit{ - ContainerID: id, - ID: id, - Pid: 0, - ExitStatus: unknownExitCode, - ExitedAt: time.Now(), - }, sandbox) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/service.go b/vendor/github.com/containerd/cri/pkg/server/service.go deleted file mode 100644 index 94e02591a..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/service.go +++ /dev/null @@ -1,325 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "time" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/plugin" - "github.com/containerd/cri/pkg/streaming" - cni "github.com/containerd/go-cni" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "google.golang.org/grpc" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/store/label" - - "github.com/containerd/cri/pkg/atomic" - criconfig "github.com/containerd/cri/pkg/config" - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - osinterface "github.com/containerd/cri/pkg/os" - "github.com/containerd/cri/pkg/registrar" - containerstore "github.com/containerd/cri/pkg/store/container" - imagestore "github.com/containerd/cri/pkg/store/image" - sandboxstore "github.com/containerd/cri/pkg/store/sandbox" - snapshotstore "github.com/containerd/cri/pkg/store/snapshot" -) - -// grpcServices are all the grpc services provided by cri containerd. -type grpcServices interface { - runtime.RuntimeServiceServer - runtime.ImageServiceServer -} - -// CRIService is the interface implement CRI remote service server. -type CRIService interface { - Run() error - // io.Closer is used by containerd to gracefully stop cri service. - io.Closer - plugin.Service - grpcServices -} - -// criService implements CRIService. -type criService struct { - // config contains all configurations. - config criconfig.Config - // imageFSPath is the path to image filesystem. - imageFSPath string - // os is an interface for all required os operations. - os osinterface.OS - // sandboxStore stores all resources associated with sandboxes. - sandboxStore *sandboxstore.Store - // sandboxNameIndex stores all sandbox names and make sure each name - // is unique. - sandboxNameIndex *registrar.Registrar - // containerStore stores all resources associated with containers. - containerStore *containerstore.Store - // containerNameIndex stores all container names and make sure each - // name is unique. - containerNameIndex *registrar.Registrar - // imageStore stores all resources associated with images. - imageStore *imagestore.Store - // snapshotStore stores information of all snapshots. - snapshotStore *snapshotstore.Store - // netPlugin is used to setup and teardown network when run/stop pod sandbox. - netPlugin cni.CNI - // client is an instance of the containerd client - client *containerd.Client - // streamServer is the streaming server serves container streaming request. - streamServer streaming.Server - // eventMonitor is the monitor monitors containerd events. - eventMonitor *eventMonitor - // initialized indicates whether the server is initialized. All GRPC services - // should return error before the server is initialized. - initialized atomic.Bool - // cniNetConfMonitor is used to reload cni network conf if there is - // any valid fs change events from cni network conf dir. - cniNetConfMonitor *cniNetConfSyncer - // baseOCISpecs contains cached OCI specs loaded via `Runtime.BaseRuntimeSpec` - baseOCISpecs map[string]*oci.Spec -} - -// NewCRIService returns a new instance of CRIService -func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIService, error) { - var err error - labels := label.NewStore() - c := &criService{ - config: config, - client: client, - os: osinterface.RealOS{}, - sandboxStore: sandboxstore.NewStore(labels), - containerStore: containerstore.NewStore(labels), - imageStore: imagestore.NewStore(client), - snapshotStore: snapshotstore.NewStore(), - sandboxNameIndex: registrar.NewRegistrar(), - containerNameIndex: registrar.NewRegistrar(), - initialized: atomic.NewBool(false), - } - - if client.SnapshotService(c.config.ContainerdConfig.Snapshotter) == nil { - return nil, errors.Errorf("failed to find snapshotter %q", c.config.ContainerdConfig.Snapshotter) - } - - c.imageFSPath = imageFSPath(config.ContainerdRootDir, config.ContainerdConfig.Snapshotter) - logrus.Infof("Get image filesystem path %q", c.imageFSPath) - - if err := c.initPlatform(); err != nil { - return nil, errors.Wrap(err, "initialize platform") - } - - // prepare streaming server - c.streamServer, err = newStreamServer(c, config.StreamServerAddress, config.StreamServerPort, config.StreamIdleTimeout) - if err != nil { - return nil, errors.Wrap(err, "failed to create stream server") - } - - c.eventMonitor = newEventMonitor(c) - - c.cniNetConfMonitor, err = newCNINetConfSyncer(c.config.NetworkPluginConfDir, c.netPlugin, c.cniLoadOptions()) - if err != nil { - return nil, errors.Wrap(err, "failed to create cni conf monitor") - } - - // Preload base OCI specs - c.baseOCISpecs, err = loadBaseOCISpecs(&config) - if err != nil { - return nil, err - } - - return c, nil -} - -// Register registers all required services onto a specific grpc server. -// This is used by containerd cri plugin. -func (c *criService) Register(s *grpc.Server) error { - return c.register(s) -} - -// RegisterTCP register all required services onto a GRPC server on TCP. -// This is used by containerd CRI plugin. -func (c *criService) RegisterTCP(s *grpc.Server) error { - if !c.config.DisableTCPService { - return c.register(s) - } - return nil -} - -// Run starts the CRI service. -func (c *criService) Run() error { - logrus.Info("Start subscribing containerd event") - c.eventMonitor.subscribe(c.client) - - logrus.Infof("Start recovering state") - if err := c.recover(ctrdutil.NamespacedContext()); err != nil { - return errors.Wrap(err, "failed to recover state") - } - - // Start event handler. - logrus.Info("Start event monitor") - eventMonitorErrCh := c.eventMonitor.start() - - // Start snapshot stats syncer, it doesn't need to be stopped. - logrus.Info("Start snapshots syncer") - snapshotsSyncer := newSnapshotsSyncer( - c.snapshotStore, - c.client.SnapshotService(c.config.ContainerdConfig.Snapshotter), - time.Duration(c.config.StatsCollectPeriod)*time.Second, - ) - snapshotsSyncer.start() - - // Start CNI network conf syncer - logrus.Info("Start cni network conf syncer") - cniNetConfMonitorErrCh := make(chan error, 1) - go func() { - defer close(cniNetConfMonitorErrCh) - cniNetConfMonitorErrCh <- c.cniNetConfMonitor.syncLoop() - }() - - // Start streaming server. - logrus.Info("Start streaming server") - streamServerErrCh := make(chan error) - go func() { - defer close(streamServerErrCh) - if err := c.streamServer.Start(true); err != nil && err != http.ErrServerClosed { - logrus.WithError(err).Error("Failed to start streaming server") - streamServerErrCh <- err - } - }() - - // Set the server as initialized. GRPC services could start serving traffic. - c.initialized.Set() - - var eventMonitorErr, streamServerErr, cniNetConfMonitorErr error - // Stop the whole CRI service if any of the critical service exits. - select { - case eventMonitorErr = <-eventMonitorErrCh: - case streamServerErr = <-streamServerErrCh: - case cniNetConfMonitorErr = <-cniNetConfMonitorErrCh: - } - if err := c.Close(); err != nil { - return errors.Wrap(err, "failed to stop cri service") - } - // If the error is set above, err from channel must be nil here, because - // the channel is supposed to be closed. Or else, we wait and set it. - if err := <-eventMonitorErrCh; err != nil { - eventMonitorErr = err - } - logrus.Info("Event monitor stopped") - // There is a race condition with http.Server.Serve. - // When `Close` is called at the same time with `Serve`, `Close` - // may finish first, and `Serve` may still block. - // See https://github.com/golang/go/issues/20239. - // Here we set a 2 second timeout for the stream server wait, - // if it timeout, an error log is generated. - // TODO(random-liu): Get rid of this after https://github.com/golang/go/issues/20239 - // is fixed. - const streamServerStopTimeout = 2 * time.Second - select { - case err := <-streamServerErrCh: - if err != nil { - streamServerErr = err - } - logrus.Info("Stream server stopped") - case <-time.After(streamServerStopTimeout): - logrus.Errorf("Stream server is not stopped in %q", streamServerStopTimeout) - } - if eventMonitorErr != nil { - return errors.Wrap(eventMonitorErr, "event monitor error") - } - if streamServerErr != nil { - return errors.Wrap(streamServerErr, "stream server error") - } - if cniNetConfMonitorErr != nil { - return errors.Wrap(cniNetConfMonitorErr, "cni network conf monitor error") - } - return nil -} - -// Close stops the CRI service. -// TODO(random-liu): Make close synchronous. -func (c *criService) Close() error { - logrus.Info("Stop CRI service") - if err := c.cniNetConfMonitor.stop(); err != nil { - logrus.WithError(err).Error("failed to stop cni network conf monitor") - } - c.eventMonitor.stop() - if err := c.streamServer.Stop(); err != nil { - return errors.Wrap(err, "failed to stop stream server") - } - return nil -} - -func (c *criService) register(s *grpc.Server) error { - instrumented := newInstrumentedService(c) - runtime.RegisterRuntimeServiceServer(s, instrumented) - runtime.RegisterImageServiceServer(s, instrumented) - return nil -} - -// imageFSPath returns containerd image filesystem path. -// Note that if containerd changes directory layout, we also needs to change this. -func imageFSPath(rootDir, snapshotter string) string { - return filepath.Join(rootDir, fmt.Sprintf("%s.%s", plugin.SnapshotPlugin, snapshotter)) -} - -func loadOCISpec(filename string) (*oci.Spec, error) { - file, err := os.Open(filename) - if err != nil { - return nil, errors.Wrapf(err, "failed to open base OCI spec: %s", filename) - } - defer file.Close() - - spec := oci.Spec{} - if err := json.NewDecoder(file).Decode(&spec); err != nil { - return nil, errors.Wrap(err, "failed to parse base OCI spec file") - } - - return &spec, nil -} - -func loadBaseOCISpecs(config *criconfig.Config) (map[string]*oci.Spec, error) { - specs := map[string]*oci.Spec{} - for _, cfg := range config.Runtimes { - if cfg.BaseRuntimeSpec == "" { - continue - } - - // Don't load same file twice - if _, ok := specs[cfg.BaseRuntimeSpec]; ok { - continue - } - - spec, err := loadOCISpec(cfg.BaseRuntimeSpec) - if err != nil { - return nil, errors.Wrapf(err, "failed to load base OCI spec from file: %s", cfg.BaseRuntimeSpec) - } - - specs[cfg.BaseRuntimeSpec] = spec - } - - return specs, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/service_unix.go b/vendor/github.com/containerd/cri/pkg/server/service_unix.go deleted file mode 100644 index a1d9c9038..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/service_unix.go +++ /dev/null @@ -1,72 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/containerd/containerd/sys" - cni "github.com/containerd/go-cni" - "github.com/opencontainers/selinux/go-selinux" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// networkAttachCount is the minimum number of networks the PodSandbox -// attaches to -const networkAttachCount = 2 - -// initPlatform handles linux specific initialization for the CRI service. -func (c *criService) initPlatform() error { - var err error - - if sys.RunningInUserNS() { - if !(c.config.DisableCgroup && !c.apparmorEnabled() && c.config.RestrictOOMScoreAdj) { - logrus.Warn("Running containerd in a user namespace typically requires disable_cgroup, disable_apparmor, restrict_oom_score_adj set to be true") - } - } - - if c.config.EnableSelinux { - if !selinux.GetEnabled() { - logrus.Warn("Selinux is not supported") - } - if r := c.config.SelinuxCategoryRange; r > 0 { - selinux.CategoryRange = uint32(r) - } - } else { - selinux.SetDisabled() - } - - // Pod needs to attach to at least loopback network and a non host network, - // hence networkAttachCount is 2. If there are more network configs the - // pod will be attached to all the networks but we will only use the ip - // of the default network interface as the pod IP. - c.netPlugin, err = cni.New(cni.WithMinNetworkCount(networkAttachCount), - cni.WithPluginConfDir(c.config.NetworkPluginConfDir), - cni.WithPluginMaxConfNum(c.config.NetworkPluginMaxConfNum), - cni.WithPluginDir([]string{c.config.NetworkPluginBinDir})) - if err != nil { - return errors.Wrap(err, "failed to initialize cni") - } - - return nil -} - -// cniLoadOptions returns cni load options for the linux. -func (c *criService) cniLoadOptions() []cni.CNIOpt { - return []cni.CNIOpt{cni.WithLoNetwork, cni.WithDefaultConf} -} diff --git a/vendor/github.com/containerd/cri/pkg/server/service_windows.go b/vendor/github.com/containerd/cri/pkg/server/service_windows.go deleted file mode 100644 index 5f764d452..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/service_windows.go +++ /dev/null @@ -1,52 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - cni "github.com/containerd/go-cni" - "github.com/pkg/errors" -) - -// windowsNetworkAttachCount is the minimum number of networks the PodSandbox -// attaches to -const windowsNetworkAttachCount = 1 - -// initPlatform handles linux specific initialization for the CRI service. -func (c *criService) initPlatform() error { - var err error - // For windows, the loopback network is added as default. - // There is no need to explicitly add one hence networkAttachCount is 1. - // If there are more network configs the pod will be attached to all the - // networks but we will only use the ip of the default network interface - // as the pod IP. - c.netPlugin, err = cni.New(cni.WithMinNetworkCount(windowsNetworkAttachCount), - cni.WithPluginConfDir(c.config.NetworkPluginConfDir), - cni.WithPluginMaxConfNum(c.config.NetworkPluginMaxConfNum), - cni.WithPluginDir([]string{c.config.NetworkPluginBinDir})) - if err != nil { - return errors.Wrap(err, "failed to initialize cni") - } - - return nil -} - -// cniLoadOptions returns cni load options for the windows. -func (c *criService) cniLoadOptions() []cni.CNIOpt { - return []cni.CNIOpt{cni.WithDefaultConf} -} diff --git a/vendor/github.com/containerd/cri/pkg/server/snapshots.go b/vendor/github.com/containerd/cri/pkg/server/snapshots.go deleted file mode 100644 index 0c1670750..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/snapshots.go +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "context" - "time" - - "github.com/containerd/containerd/errdefs" - snapshot "github.com/containerd/containerd/snapshots" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - snapshotstore "github.com/containerd/cri/pkg/store/snapshot" -) - -// snapshotsSyncer syncs snapshot stats periodically. imagefs info and container stats -// should both use cached result here. -// TODO(random-liu): Benchmark with high workload. We may need a statsSyncer instead if -// benchmark result shows that container cpu/memory stats also need to be cached. -type snapshotsSyncer struct { - store *snapshotstore.Store - snapshotter snapshot.Snapshotter - syncPeriod time.Duration -} - -// newSnapshotsSyncer creates a snapshot syncer. -func newSnapshotsSyncer(store *snapshotstore.Store, snapshotter snapshot.Snapshotter, - period time.Duration) *snapshotsSyncer { - return &snapshotsSyncer{ - store: store, - snapshotter: snapshotter, - syncPeriod: period, - } -} - -// start starts the snapshots syncer. No stop function is needed because -// the syncer doesn't update any persistent states, it's fine to let it -// exit with the process. -func (s *snapshotsSyncer) start() { - tick := time.NewTicker(s.syncPeriod) - go func() { - defer tick.Stop() - // TODO(random-liu): This is expensive. We should do benchmark to - // check the resource usage and optimize this. - for { - if err := s.sync(); err != nil { - logrus.WithError(err).Error("Failed to sync snapshot stats") - } - <-tick.C - } - }() -} - -// sync updates all snapshots stats. -func (s *snapshotsSyncer) sync() error { - ctx := ctrdutil.NamespacedContext() - start := time.Now().UnixNano() - var snapshots []snapshot.Info - // Do not call `Usage` directly in collect function, because - // `Usage` takes time, we don't want `Walk` to hold read lock - // of snapshot metadata store for too long time. - // TODO(random-liu): Set timeout for the following 2 contexts. - if err := s.snapshotter.Walk(ctx, func(ctx context.Context, info snapshot.Info) error { - snapshots = append(snapshots, info) - return nil - }); err != nil { - return errors.Wrap(err, "walk all snapshots failed") - } - for _, info := range snapshots { - sn, err := s.store.Get(info.Name) - if err == nil { - // Only update timestamp for non-active snapshot. - if sn.Kind == info.Kind && sn.Kind != snapshot.KindActive { - sn.Timestamp = time.Now().UnixNano() - s.store.Add(sn) - continue - } - } - // Get newest stats if the snapshot is new or active. - sn = snapshotstore.Snapshot{ - Key: info.Name, - Kind: info.Kind, - Timestamp: time.Now().UnixNano(), - } - usage, err := s.snapshotter.Usage(ctx, info.Name) - if err != nil { - if !errdefs.IsNotFound(err) { - logrus.WithError(err).Errorf("Failed to get usage for snapshot %q", info.Name) - } - continue - } - sn.Size = uint64(usage.Size) - sn.Inodes = uint64(usage.Inodes) - s.store.Add(sn) - } - for _, sn := range s.store.List() { - if sn.Timestamp >= start { - continue - } - // Delete the snapshot stats if it's not updated this time. - s.store.Delete(sn.Key) - } - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/status.go b/vendor/github.com/containerd/cri/pkg/server/status.go deleted file mode 100644 index 4283a5190..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/status.go +++ /dev/null @@ -1,83 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "encoding/json" - "fmt" - goruntime "runtime" - - "github.com/containerd/containerd/log" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// networkNotReadyReason is the reason reported when network is not ready. -const networkNotReadyReason = "NetworkPluginNotReady" - -// Status returns the status of the runtime. -func (c *criService) Status(ctx context.Context, r *runtime.StatusRequest) (*runtime.StatusResponse, error) { - // As a containerd plugin, if CRI plugin is serving request, - // containerd must be ready. - runtimeCondition := &runtime.RuntimeCondition{ - Type: runtime.RuntimeReady, - Status: true, - } - networkCondition := &runtime.RuntimeCondition{ - Type: runtime.NetworkReady, - Status: true, - } - // Check the status of the cni initialization - if err := c.netPlugin.Status(); err != nil { - networkCondition.Status = false - networkCondition.Reason = networkNotReadyReason - networkCondition.Message = fmt.Sprintf("Network plugin returns error: %v", err) - } - - resp := &runtime.StatusResponse{ - Status: &runtime.RuntimeStatus{Conditions: []*runtime.RuntimeCondition{ - runtimeCondition, - networkCondition, - }}, - } - if r.Verbose { - configByt, err := json.Marshal(c.config) - if err != nil { - return nil, err - } - resp.Info = make(map[string]string) - resp.Info["config"] = string(configByt) - versionByt, err := json.Marshal(goruntime.Version()) - if err != nil { - return nil, err - } - resp.Info["golang"] = string(versionByt) - - cniConfig, err := json.Marshal(c.netPlugin.GetConfig()) - if err != nil { - log.G(ctx).WithError(err).Errorf("Failed to marshal CNI config %v", err) - } - resp.Info["cniconfig"] = string(cniConfig) - - lastCNILoadStatus := "OK" - if lerr := c.cniNetConfMonitor.lastStatus(); lerr != nil { - lastCNILoadStatus = lerr.Error() - } - resp.Info["lastCNILoadStatus"] = lastCNILoadStatus - } - return resp, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/streaming.go b/vendor/github.com/containerd/cri/pkg/server/streaming.go deleted file mode 100644 index d0089cc89..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/streaming.go +++ /dev/null @@ -1,239 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "context" - "crypto/tls" - "io" - "math" - "net" - "os" - "time" - - "github.com/pkg/errors" - k8snet "k8s.io/apimachinery/pkg/util/net" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/tools/remotecommand" - k8scert "k8s.io/client-go/util/cert" - "k8s.io/utils/exec" - - ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/streaming" -) - -type streamListenerMode int - -const ( - x509KeyPairTLS streamListenerMode = iota - selfSignTLS - withoutTLS -) - -func getStreamListenerMode(c *criService) (streamListenerMode, error) { - if c.config.EnableTLSStreaming { - if c.config.X509KeyPairStreaming.TLSCertFile != "" && c.config.X509KeyPairStreaming.TLSKeyFile != "" { - return x509KeyPairTLS, nil - } - if c.config.X509KeyPairStreaming.TLSCertFile != "" && c.config.X509KeyPairStreaming.TLSKeyFile == "" { - return -1, errors.New("must set X509KeyPairStreaming.TLSKeyFile") - } - if c.config.X509KeyPairStreaming.TLSCertFile == "" && c.config.X509KeyPairStreaming.TLSKeyFile != "" { - return -1, errors.New("must set X509KeyPairStreaming.TLSCertFile") - } - return selfSignTLS, nil - } - if c.config.X509KeyPairStreaming.TLSCertFile != "" { - return -1, errors.New("X509KeyPairStreaming.TLSCertFile is set but EnableTLSStreaming is not set") - } - if c.config.X509KeyPairStreaming.TLSKeyFile != "" { - return -1, errors.New("X509KeyPairStreaming.TLSKeyFile is set but EnableTLSStreaming is not set") - } - return withoutTLS, nil -} - -func newStreamServer(c *criService, addr, port, streamIdleTimeout string) (streaming.Server, error) { - if addr == "" { - a, err := k8snet.ResolveBindAddress(nil) - if err != nil { - return nil, errors.Wrap(err, "failed to get stream server address") - } - addr = a.String() - } - config := streaming.DefaultConfig - if streamIdleTimeout != "" { - var err error - config.StreamIdleTimeout, err = time.ParseDuration(streamIdleTimeout) - if err != nil { - return nil, errors.Wrap(err, "invalid stream idle timeout") - } - } - config.Addr = net.JoinHostPort(addr, port) - run := newStreamRuntime(c) - tlsMode, err := getStreamListenerMode(c) - if err != nil { - return nil, errors.Wrapf(err, "invalid stream server configuration") - } - switch tlsMode { - case x509KeyPairTLS: - tlsCert, err := tls.LoadX509KeyPair(c.config.X509KeyPairStreaming.TLSCertFile, c.config.X509KeyPairStreaming.TLSKeyFile) - if err != nil { - return nil, errors.Wrap(err, "failed to load x509 key pair for stream server") - } - config.TLSConfig = &tls.Config{ - Certificates: []tls.Certificate{tlsCert}, - } - return streaming.NewServer(config, run) - case selfSignTLS: - tlsCert, err := newTLSCert() - if err != nil { - return nil, errors.Wrap(err, "failed to generate tls certificate for stream server") - } - config.TLSConfig = &tls.Config{ - Certificates: []tls.Certificate{tlsCert}, - InsecureSkipVerify: true, - } - return streaming.NewServer(config, run) - case withoutTLS: - return streaming.NewServer(config, run) - default: - return nil, errors.New("invalid configuration for the stream listener") - } -} - -type streamRuntime struct { - c *criService -} - -func newStreamRuntime(c *criService) streaming.Runtime { - return &streamRuntime{c: c} -} - -// Exec executes a command inside the container. exec.ExitError is returned if the command -// returns non-zero exit code. -func (s *streamRuntime) Exec(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, - tty bool, resize <-chan remotecommand.TerminalSize) error { - exitCode, err := s.c.execInContainer(ctrdutil.NamespacedContext(), containerID, execOptions{ - cmd: cmd, - stdin: stdin, - stdout: stdout, - stderr: stderr, - tty: tty, - resize: resize, - }) - if err != nil { - return errors.Wrap(err, "failed to exec in container") - } - if *exitCode == 0 { - return nil - } - return &exec.CodeExitError{ - Err: errors.Errorf("error executing command %v, exit code %d", cmd, *exitCode), - Code: int(*exitCode), - } -} - -func (s *streamRuntime) Attach(containerID string, in io.Reader, out, err io.WriteCloser, tty bool, - resize <-chan remotecommand.TerminalSize) error { - return s.c.attachContainer(ctrdutil.NamespacedContext(), containerID, in, out, err, tty, resize) -} - -func (s *streamRuntime) PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error { - if port <= 0 || port > math.MaxUint16 { - return errors.Errorf("invalid port %d", port) - } - ctx := ctrdutil.NamespacedContext() - return s.c.portForward(ctx, podSandboxID, port, stream) -} - -// handleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each -// remotecommand.TerminalSize received from the channel. -func handleResizing(ctx context.Context, resize <-chan remotecommand.TerminalSize, resizeFunc func(size remotecommand.TerminalSize)) { - if resize == nil { - return - } - - go func() { - defer runtime.HandleCrash() - - for { - select { - case <-ctx.Done(): - return - case size, ok := <-resize: - if !ok { - return - } - if size.Height < 1 || size.Width < 1 { - continue - } - resizeFunc(size) - } - } - }() -} - -// newTLSCert returns a self CA signed tls.certificate. -// TODO (mikebrow): replace / rewrite this function to support using CA -// signing of the certificate. Requires a security plan for kubernetes regarding -// CRI connections / streaming, etc. For example, kubernetes could configure or -// require a CA service and pass a configuration down through CRI. -func newTLSCert() (tls.Certificate, error) { - fail := func(err error) (tls.Certificate, error) { return tls.Certificate{}, err } - - hostName, err := os.Hostname() - if err != nil { - return fail(errors.Wrap(err, "failed to get hostname")) - } - - addrs, err := net.InterfaceAddrs() - if err != nil { - return fail(errors.Wrap(err, "failed to get host IP addresses")) - } - - var alternateIPs []net.IP - var alternateDNS []string - for _, addr := range addrs { - var ip net.IP - - switch v := addr.(type) { - case *net.IPNet: - ip = v.IP - case *net.IPAddr: - ip = v.IP - default: - continue - } - - alternateIPs = append(alternateIPs, ip) - alternateDNS = append(alternateDNS, ip.String()) - } - - // Generate a self signed certificate key (CA is self) - certPem, keyPem, err := k8scert.GenerateSelfSignedCertKey(hostName, alternateIPs, alternateDNS) - if err != nil { - return fail(errors.Wrap(err, "certificate key could not be created")) - } - - // Load the tls certificate - tlsCert, err := tls.X509KeyPair(certPem, keyPem) - if err != nil { - return fail(errors.Wrap(err, "certificate could not be loaded")) - } - - return tlsCert, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go b/vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go deleted file mode 100644 index 6c725e234..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go +++ /dev/null @@ -1,128 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "net" - "os" - "path/filepath" - "strings" - "text/template" - - "github.com/containerd/containerd/log" - "github.com/pkg/errors" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// cniConfigTemplate contains the values containerd will overwrite -// in the cni config template. -type cniConfigTemplate struct { - // PodCIDR is the cidr for pods on the node. - PodCIDR string - // PodCIDRRanges is the cidr ranges for pods on the node. - PodCIDRRanges []string - // Routes is a list of routes configured. - Routes []string -} - -const ( - // cniConfigFileName is the name of cni config file generated by containerd. - cniConfigFileName = "10-containerd-net.conflist" - // zeroCIDRv6 is the null route for IPv6. - zeroCIDRv6 = "::/0" - // zeroCIDRv4 is the null route for IPv4. - zeroCIDRv4 = "0.0.0.0/0" -) - -// UpdateRuntimeConfig updates the runtime config. Currently only handles podCIDR updates. -func (c *criService) UpdateRuntimeConfig(ctx context.Context, r *runtime.UpdateRuntimeConfigRequest) (*runtime.UpdateRuntimeConfigResponse, error) { - podCIDRs := r.GetRuntimeConfig().GetNetworkConfig().GetPodCidr() - if podCIDRs == "" { - return &runtime.UpdateRuntimeConfigResponse{}, nil - } - cidrs := strings.Split(podCIDRs, ",") - for i := range cidrs { - cidrs[i] = strings.TrimSpace(cidrs[i]) - } - routes, err := getRoutes(cidrs) - if err != nil { - return nil, errors.Wrap(err, "get routes") - } - - confTemplate := c.config.NetworkPluginConfTemplate - if confTemplate == "" { - log.G(ctx).Info("No cni config template is specified, wait for other system components to drop the config.") - return &runtime.UpdateRuntimeConfigResponse{}, nil - } - if err := c.netPlugin.Status(); err == nil { - log.G(ctx).Infof("Network plugin is ready, skip generating cni config from template %q", confTemplate) - return &runtime.UpdateRuntimeConfigResponse{}, nil - } else if err := c.netPlugin.Load(c.cniLoadOptions()...); err == nil { - log.G(ctx).Infof("CNI config is successfully loaded, skip generating cni config from template %q", confTemplate) - return &runtime.UpdateRuntimeConfigResponse{}, nil - } - log.G(ctx).Infof("Generating cni config from template %q", confTemplate) - // generate cni config file from the template with updated pod cidr. - t, err := template.ParseFiles(confTemplate) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse cni config template %q", confTemplate) - } - if err := os.MkdirAll(c.config.NetworkPluginConfDir, 0755); err != nil { - return nil, errors.Wrapf(err, "failed to create cni config directory: %q", c.config.NetworkPluginConfDir) - } - confFile := filepath.Join(c.config.NetworkPluginConfDir, cniConfigFileName) - f, err := os.OpenFile(confFile, os.O_WRONLY|os.O_CREATE, 0644) - if err != nil { - return nil, errors.Wrapf(err, "failed to open cni config file %q", confFile) - } - defer f.Close() - if err := t.Execute(f, cniConfigTemplate{ - PodCIDR: cidrs[0], - PodCIDRRanges: cidrs, - Routes: routes, - }); err != nil { - return nil, errors.Wrapf(err, "failed to generate cni config file %q", confFile) - } - return &runtime.UpdateRuntimeConfigResponse{}, nil -} - -// getRoutes generates required routes for the passed in cidrs. -func getRoutes(cidrs []string) ([]string, error) { - var ( - routes []string - hasV4, hasV6 bool - ) - for _, c := range cidrs { - _, cidr, err := net.ParseCIDR(c) - if err != nil { - return nil, err - } - if cidr.IP.To4() != nil { - hasV4 = true - } else { - hasV6 = true - } - } - if hasV4 { - routes = append(routes, zeroCIDRv4) - } - if hasV6 { - routes = append(routes, zeroCIDRv6) - } - return routes, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/server/version.go b/vendor/github.com/containerd/cri/pkg/server/version.go deleted file mode 100644 index c1dea50c1..000000000 --- a/vendor/github.com/containerd/cri/pkg/server/version.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package server - -import ( - "github.com/containerd/containerd/version" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/constants" -) - -const ( - containerName = "containerd" - // kubeAPIVersion is the api version of kubernetes. - // TODO(random-liu): Change this to actual CRI version. - kubeAPIVersion = "0.1.0" -) - -// Version returns the runtime name, runtime version and runtime API version. -func (c *criService) Version(ctx context.Context, r *runtime.VersionRequest) (*runtime.VersionResponse, error) { - return &runtime.VersionResponse{ - Version: kubeAPIVersion, - RuntimeName: containerName, - RuntimeVersion: version.Version, - RuntimeApiVersion: constants.CRIVersion, - }, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/seutil/seutil.go b/vendor/github.com/containerd/cri/pkg/seutil/seutil.go deleted file mode 100644 index f453a7775..000000000 --- a/vendor/github.com/containerd/cri/pkg/seutil/seutil.go +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package seutil - -import ( - "bufio" - "os" - - "github.com/opencontainers/selinux/go-selinux" -) - -var seTypes map[string]struct{} - -const typePath = "/etc/selinux/targeted/contexts/customizable_types" - -func init() { - seTypes = make(map[string]struct{}) - if !selinux.GetEnabled() { - return - } - f, err := os.Open(typePath) - if err != nil { - return - } - defer f.Close() - s := bufio.NewScanner(f) - for s.Scan() { - seTypes[s.Text()] = struct{}{} - } -} - -// HasType returns true if the underlying system has the -// provided selinux type enabled. -func HasType(name string) bool { - _, ok := seTypes[name] - return ok -} - -// ChangeToKVM process label -func ChangeToKVM(l string) (string, error) { - if l == "" || !selinux.GetEnabled() { - return "", nil - } - proc, _ := selinux.KVMContainerLabels() - selinux.ReleaseLabel(proc) - - current, err := selinux.NewContext(l) - if err != nil { - return "", err - } - next, err := selinux.NewContext(proc) - if err != nil { - return "", err - } - current["type"] = next["type"] - return current.Get(), nil -} diff --git a/vendor/github.com/containerd/cri/pkg/store/container/container.go b/vendor/github.com/containerd/cri/pkg/store/container/container.go deleted file mode 100644 index 53c0745a5..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/container/container.go +++ /dev/null @@ -1,177 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package container - -import ( - "sync" - - "github.com/containerd/containerd" - "github.com/containerd/cri/pkg/store/label" - "github.com/docker/docker/pkg/truncindex" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - cio "github.com/containerd/cri/pkg/server/io" - "github.com/containerd/cri/pkg/store" -) - -// Container contains all resources associated with the container. All methods to -// mutate the internal state are thread-safe. -type Container struct { - // Metadata is the metadata of the container, it is **immutable** after created. - Metadata - // Status stores the status of the container. - Status StatusStorage - // Container is the containerd container client. - Container containerd.Container - // Container IO. - // IO could only be nil when the container is in unknown state. - IO *cio.ContainerIO - // StopCh is used to propagate the stop information of the container. - *store.StopCh -} - -// Opts sets specific information to newly created Container. -type Opts func(*Container) error - -// WithContainer adds the containerd Container to the internal data store. -func WithContainer(cntr containerd.Container) Opts { - return func(c *Container) error { - c.Container = cntr - return nil - } -} - -// WithContainerIO adds IO into the container. -func WithContainerIO(io *cio.ContainerIO) Opts { - return func(c *Container) error { - c.IO = io - return nil - } -} - -// WithStatus adds status to the container. -func WithStatus(status Status, root string) Opts { - return func(c *Container) error { - s, err := StoreStatus(root, c.ID, status) - if err != nil { - return err - } - c.Status = s - if s.Get().State() == runtime.ContainerState_CONTAINER_EXITED { - c.Stop() - } - return nil - } -} - -// NewContainer creates an internally used container type. -func NewContainer(metadata Metadata, opts ...Opts) (Container, error) { - c := Container{ - Metadata: metadata, - StopCh: store.NewStopCh(), - } - for _, o := range opts { - if err := o(&c); err != nil { - return Container{}, err - } - } - return c, nil -} - -// Delete deletes checkpoint for the container. -func (c *Container) Delete() error { - return c.Status.Delete() -} - -// Store stores all Containers. -type Store struct { - lock sync.RWMutex - containers map[string]Container - idIndex *truncindex.TruncIndex - labels *label.Store -} - -// NewStore creates a container store. -func NewStore(labels *label.Store) *Store { - return &Store{ - containers: make(map[string]Container), - idIndex: truncindex.NewTruncIndex([]string{}), - labels: labels, - } -} - -// Add a container into the store. Returns store.ErrAlreadyExist if the -// container already exists. -func (s *Store) Add(c Container) error { - s.lock.Lock() - defer s.lock.Unlock() - if _, ok := s.containers[c.ID]; ok { - return store.ErrAlreadyExist - } - if err := s.labels.Reserve(c.ProcessLabel); err != nil { - return err - } - if err := s.idIndex.Add(c.ID); err != nil { - return err - } - s.containers[c.ID] = c - return nil -} - -// Get returns the container with specified id. Returns store.ErrNotExist -// if the container doesn't exist. -func (s *Store) Get(id string) (Container, error) { - s.lock.RLock() - defer s.lock.RUnlock() - id, err := s.idIndex.Get(id) - if err != nil { - if err == truncindex.ErrNotExist { - err = store.ErrNotExist - } - return Container{}, err - } - if c, ok := s.containers[id]; ok { - return c, nil - } - return Container{}, store.ErrNotExist -} - -// List lists all containers. -func (s *Store) List() []Container { - s.lock.RLock() - defer s.lock.RUnlock() - var containers []Container - for _, c := range s.containers { - containers = append(containers, c) - } - return containers -} - -// Delete deletes the container from store with specified id. -func (s *Store) Delete(id string) { - s.lock.Lock() - defer s.lock.Unlock() - id, err := s.idIndex.Get(id) - if err != nil { - // Note: The idIndex.Delete and delete doesn't handle truncated index. - // So we need to return if there are error. - return - } - s.labels.Release(s.containers[id].ProcessLabel) - s.idIndex.Delete(id) // nolint: errcheck - delete(s.containers, id) -} diff --git a/vendor/github.com/containerd/cri/pkg/store/container/fake_status.go b/vendor/github.com/containerd/cri/pkg/store/container/fake_status.go deleted file mode 100644 index 756588152..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/container/fake_status.go +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package container - -import "sync" - -// WithFakeStatus adds fake status to the container. -func WithFakeStatus(status Status) Opts { - return func(c *Container) error { - c.Status = &fakeStatusStorage{status: status} - if status.FinishedAt != 0 { - // Fake the TaskExit event - c.Stop() - } - return nil - } -} - -// fakeStatusStorage is a fake status storage for testing. -type fakeStatusStorage struct { - sync.RWMutex - status Status -} - -func (f *fakeStatusStorage) Get() Status { - f.RLock() - defer f.RUnlock() - return f.status -} - -func (f *fakeStatusStorage) UpdateSync(u UpdateFunc) error { - return f.Update(u) -} - -func (f *fakeStatusStorage) Update(u UpdateFunc) error { - f.Lock() - defer f.Unlock() - newStatus, err := u(f.status) - if err != nil { - return err - } - f.status = newStatus - return nil -} - -func (f *fakeStatusStorage) Delete() error { - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/store/container/metadata.go b/vendor/github.com/containerd/cri/pkg/store/container/metadata.go deleted file mode 100644 index ff9b5f2a3..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/container/metadata.go +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package container - -import ( - "encoding/json" - - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// NOTE(random-liu): -// 1) Metadata is immutable after created. -// 2) Metadata is checkpointed as containerd container label. - -// metadataVersion is current version of container metadata. -const metadataVersion = "v1" // nolint - -// versionedMetadata is the internal versioned container metadata. -// nolint -type versionedMetadata struct { - // Version indicates the version of the versioned container metadata. - Version string - // Metadata's type is metadataInternal. If not there will be a recursive call in MarshalJSON. - Metadata metadataInternal -} - -// metadataInternal is for internal use. -type metadataInternal Metadata - -// Metadata is the unversioned container metadata. -type Metadata struct { - // ID is the container id. - ID string - // Name is the container name. - Name string - // SandboxID is the sandbox id the container belongs to. - SandboxID string - // Config is the CRI container config. - // NOTE(random-liu): Resource limits are updatable, the source - // of truth for resource limits are in containerd. - Config *runtime.ContainerConfig - // ImageRef is the reference of image used by the container. - ImageRef string - // LogPath is the container log path. - LogPath string - // StopSignal is the system call signal that will be sent to the container to exit. - // TODO(random-liu): Add integration test for stop signal. - StopSignal string - // ProcessLabel is the SELinux process label for the container - ProcessLabel string -} - -// MarshalJSON encodes Metadata into bytes in json format. -func (c *Metadata) MarshalJSON() ([]byte, error) { - return json.Marshal(&versionedMetadata{ - Version: metadataVersion, - Metadata: metadataInternal(*c), - }) -} - -// UnmarshalJSON decodes Metadata from bytes. -func (c *Metadata) UnmarshalJSON(data []byte) error { - versioned := &versionedMetadata{} - if err := json.Unmarshal(data, versioned); err != nil { - return err - } - // Handle old version after upgrade. - switch versioned.Version { - case metadataVersion: - *c = Metadata(versioned.Metadata) - return nil - } - return errors.Errorf("unsupported version: %q", versioned.Version) -} diff --git a/vendor/github.com/containerd/cri/pkg/store/container/status.go b/vendor/github.com/containerd/cri/pkg/store/container/status.go deleted file mode 100644 index 655f58806..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/container/status.go +++ /dev/null @@ -1,247 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package container - -import ( - "encoding/json" - "io/ioutil" - "os" - "path/filepath" - "sync" - - "github.com/containerd/continuity" - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// The container state machine in the CRI plugin: -// -// + + -// | | -// | Create | Load -// | | -// +----v----+ | -// | | | -// | CREATED <---------+-----------+ -// | | | | -// +----+----- | | -// | | | -// | Start | | -// | | | -// +----v----+ | | -// Exec +--------+ | | | -// Attach | | RUNNING <---------+ | -// LogReopen +--------> | | | -// +----+----+ | | -// | | | -// | Stop/Exit | | -// | | | -// +----v----+ | | -// | <---------+ +----v----+ -// | EXITED | | | -// | <----------------+ UNKNOWN | -// +----+----+ Stop | | -// | +---------+ -// | Remove -// v -// DELETED - -// statusVersion is current version of container status. -const statusVersion = "v1" // nolint - -// versionedStatus is the internal used versioned container status. -// nolint -type versionedStatus struct { - // Version indicates the version of the versioned container status. - Version string - Status -} - -// Status is the status of a container. -type Status struct { - // Pid is the init process id of the container. - Pid uint32 - // CreatedAt is the created timestamp. - CreatedAt int64 - // StartedAt is the started timestamp. - StartedAt int64 - // FinishedAt is the finished timestamp. - FinishedAt int64 - // ExitCode is the container exit code. - ExitCode int32 - // CamelCase string explaining why container is in its current state. - Reason string - // Human-readable message indicating details about why container is in its - // current state. - Message string - // Starting indicates that the container is in starting state. - // This field doesn't need to be checkpointed. - Starting bool `json:"-"` - // Removing indicates that the container is in removing state. - // This field doesn't need to be checkpointed. - Removing bool `json:"-"` - // Unknown indicates that the container status is not fully loaded. - // This field doesn't need to be checkpointed. - Unknown bool `json:"-"` -} - -// State returns current state of the container based on the container status. -func (s Status) State() runtime.ContainerState { - if s.Unknown { - return runtime.ContainerState_CONTAINER_UNKNOWN - } - if s.FinishedAt != 0 { - return runtime.ContainerState_CONTAINER_EXITED - } - if s.StartedAt != 0 { - return runtime.ContainerState_CONTAINER_RUNNING - } - if s.CreatedAt != 0 { - return runtime.ContainerState_CONTAINER_CREATED - } - return runtime.ContainerState_CONTAINER_UNKNOWN -} - -// encode encodes Status into bytes in json format. -func (s *Status) encode() ([]byte, error) { - return json.Marshal(&versionedStatus{ - Version: statusVersion, - Status: *s, - }) -} - -// decode decodes Status from bytes. -func (s *Status) decode(data []byte) error { - versioned := &versionedStatus{} - if err := json.Unmarshal(data, versioned); err != nil { - return err - } - // Handle old version after upgrade. - switch versioned.Version { - case statusVersion: - *s = versioned.Status - return nil - } - return errors.New("unsupported version") -} - -// UpdateFunc is function used to update the container status. If there -// is an error, the update will be rolled back. -type UpdateFunc func(Status) (Status, error) - -// StatusStorage manages the container status with a storage backend. -type StatusStorage interface { - // Get a container status. - Get() Status - // UpdateSync updates the container status and the on disk checkpoint. - // Note that the update MUST be applied in one transaction. - UpdateSync(UpdateFunc) error - // Update the container status. Note that the update MUST be applied - // in one transaction. - Update(UpdateFunc) error - // Delete the container status. - // Note: - // * Delete should be idempotent. - // * The status must be deleted in one trasaction. - Delete() error -} - -// StoreStatus creates the storage containing the passed in container status with the -// specified id. -// The status MUST be created in one transaction. -func StoreStatus(root, id string, status Status) (StatusStorage, error) { - data, err := status.encode() - if err != nil { - return nil, errors.Wrap(err, "failed to encode status") - } - path := filepath.Join(root, "status") - if err := continuity.AtomicWriteFile(path, data, 0600); err != nil { - return nil, errors.Wrapf(err, "failed to checkpoint status to %q", path) - } - return &statusStorage{ - path: path, - status: status, - }, nil -} - -// LoadStatus loads container status from checkpoint. There shouldn't be threads -// writing to the file during loading. -func LoadStatus(root, id string) (Status, error) { - path := filepath.Join(root, "status") - data, err := ioutil.ReadFile(path) - if err != nil { - return Status{}, errors.Wrapf(err, "failed to read status from %q", path) - } - var status Status - if err := status.decode(data); err != nil { - return Status{}, errors.Wrapf(err, "failed to decode status %q", data) - } - return status, nil -} - -type statusStorage struct { - sync.RWMutex - path string - status Status -} - -// Get a copy of container status. -func (s *statusStorage) Get() Status { - s.RLock() - defer s.RUnlock() - return s.status -} - -// UpdateSync updates the container status and the on disk checkpoint. -func (s *statusStorage) UpdateSync(u UpdateFunc) error { - s.Lock() - defer s.Unlock() - newStatus, err := u(s.status) - if err != nil { - return err - } - data, err := newStatus.encode() - if err != nil { - return errors.Wrap(err, "failed to encode status") - } - if err := continuity.AtomicWriteFile(s.path, data, 0600); err != nil { - return errors.Wrapf(err, "failed to checkpoint status to %q", s.path) - } - s.status = newStatus - return nil -} - -// Update the container status. -func (s *statusStorage) Update(u UpdateFunc) error { - s.Lock() - defer s.Unlock() - newStatus, err := u(s.status) - if err != nil { - return err - } - s.status = newStatus - return nil -} - -// Delete deletes the container status from disk atomically. -func (s *statusStorage) Delete() error { - temp := filepath.Dir(s.path) + ".del-" + filepath.Base(s.path) - if err := os.Rename(s.path, temp); err != nil && !os.IsNotExist(err) { - return err - } - return os.RemoveAll(temp) -} diff --git a/vendor/github.com/containerd/cri/pkg/store/errors.go b/vendor/github.com/containerd/cri/pkg/store/errors.go deleted file mode 100644 index d8398e45f..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/errors.go +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package store - -import "github.com/containerd/containerd/errdefs" - -var ( - // ErrAlreadyExist is the error returned when data added in the store - // already exists. - // - // This error has been DEPRECATED and will be removed in 1.5. Please switch - // usage directly to `errdefs.ErrAlreadyExists`. - ErrAlreadyExist = errdefs.ErrAlreadyExists - // ErrNotExist is the error returned when data is not in the store. - // - // This error has been DEPRECATED and will be removed in 1.5. Please switch - // usage directly to `errdefs.ErrNotFound`. - ErrNotExist = errdefs.ErrNotFound -) diff --git a/vendor/github.com/containerd/cri/pkg/store/image/fake_image.go b/vendor/github.com/containerd/cri/pkg/store/image/fake_image.go deleted file mode 100644 index e1d6b7cd4..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/image/fake_image.go +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package image - -import "github.com/pkg/errors" - -// NewFakeStore returns an image store with predefined images. -// Update is not allowed for this fake store. -func NewFakeStore(images []Image) (*Store, error) { - s := NewStore(nil) - for _, i := range images { - for _, ref := range i.References { - s.refCache[ref] = i.ID - } - if err := s.store.add(i); err != nil { - return nil, errors.Wrapf(err, "add image %+v", i) - } - } - return s, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/store/image/image.go b/vendor/github.com/containerd/cri/pkg/store/image/image.go deleted file mode 100644 index 208d490db..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/image/image.go +++ /dev/null @@ -1,256 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package image - -import ( - "context" - "encoding/json" - "sync" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - imagedigest "github.com/opencontainers/go-digest" - "github.com/opencontainers/go-digest/digestset" - imageidentity "github.com/opencontainers/image-spec/identity" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - - storeutil "github.com/containerd/cri/pkg/store" - "github.com/containerd/cri/pkg/util" -) - -// Image contains all resources associated with the image. All fields -// MUST not be mutated directly after created. -type Image struct { - // Id of the image. Normally the digest of image config. - ID string - // References are references to the image, e.g. RepoTag and RepoDigest. - References []string - // ChainID is the chainID of the image. - ChainID string - // Size is the compressed size of the image. - Size int64 - // ImageSpec is the oci image structure which describes basic information about the image. - ImageSpec imagespec.Image -} - -// Store stores all images. -type Store struct { - lock sync.RWMutex - // refCache is a containerd image reference to image id cache. - refCache map[string]string - // client is the containerd client. - client *containerd.Client - // store is the internal image store indexed by image id. - store *store -} - -// NewStore creates an image store. -func NewStore(client *containerd.Client) *Store { - return &Store{ - refCache: make(map[string]string), - client: client, - store: &store{ - images: make(map[string]Image), - digestSet: digestset.NewSet(), - }, - } -} - -// Update updates cache for a reference. -func (s *Store) Update(ctx context.Context, ref string) error { - s.lock.Lock() - defer s.lock.Unlock() - i, err := s.client.GetImage(ctx, ref) - if err != nil && !errdefs.IsNotFound(err) { - return errors.Wrap(err, "get image from containerd") - } - var img *Image - if err == nil { - img, err = getImage(ctx, i) - if err != nil { - return errors.Wrap(err, "get image info from containerd") - } - } - return s.update(ref, img) -} - -// update updates the internal cache. img == nil means that -// the image does not exist in containerd. -func (s *Store) update(ref string, img *Image) error { - oldID, oldExist := s.refCache[ref] - if img == nil { - // The image reference doesn't exist in containerd. - if oldExist { - // Remove the reference from the store. - s.store.delete(oldID, ref) - delete(s.refCache, ref) - } - return nil - } - if oldExist { - if oldID == img.ID { - return nil - } - // Updated. Remove tag from old image. - s.store.delete(oldID, ref) - } - // New image. Add new image. - s.refCache[ref] = img.ID - return s.store.add(*img) -} - -// getImage gets image information from containerd. -func getImage(ctx context.Context, i containerd.Image) (*Image, error) { - // Get image information. - diffIDs, err := i.RootFS(ctx) - if err != nil { - return nil, errors.Wrap(err, "get image diffIDs") - } - chainID := imageidentity.ChainID(diffIDs) - - size, err := i.Size(ctx) - if err != nil { - return nil, errors.Wrap(err, "get image compressed resource size") - } - - desc, err := i.Config(ctx) - if err != nil { - return nil, errors.Wrap(err, "get image config descriptor") - } - id := desc.Digest.String() - - rb, err := content.ReadBlob(ctx, i.ContentStore(), desc) - if err != nil { - return nil, errors.Wrap(err, "read image config from content store") - } - var ociimage imagespec.Image - if err := json.Unmarshal(rb, &ociimage); err != nil { - return nil, errors.Wrapf(err, "unmarshal image config %s", rb) - } - - return &Image{ - ID: id, - References: []string{i.Name()}, - ChainID: chainID.String(), - Size: size, - ImageSpec: ociimage, - }, nil -} - -// Resolve resolves a image reference to image id. -func (s *Store) Resolve(ref string) (string, error) { - s.lock.RLock() - defer s.lock.RUnlock() - id, ok := s.refCache[ref] - if !ok { - return "", storeutil.ErrNotExist - } - return id, nil -} - -// Get gets image metadata by image id. The id can be truncated. -// Returns various validation errors if the image id is invalid. -// Returns storeutil.ErrNotExist if the image doesn't exist. -func (s *Store) Get(id string) (Image, error) { - return s.store.get(id) -} - -// List lists all images. -func (s *Store) List() []Image { - return s.store.list() -} - -type store struct { - lock sync.RWMutex - images map[string]Image - digestSet *digestset.Set -} - -func (s *store) list() []Image { - s.lock.RLock() - defer s.lock.RUnlock() - var images []Image - for _, i := range s.images { - images = append(images, i) - } - return images -} - -func (s *store) add(img Image) error { - s.lock.Lock() - defer s.lock.Unlock() - if _, err := s.digestSet.Lookup(img.ID); err != nil { - if err != digestset.ErrDigestNotFound { - return err - } - if err := s.digestSet.Add(imagedigest.Digest(img.ID)); err != nil { - return err - } - } - - i, ok := s.images[img.ID] - if !ok { - // If the image doesn't exist, add it. - s.images[img.ID] = img - return nil - } - // Or else, merge the references. - i.References = util.MergeStringSlices(i.References, img.References) - s.images[img.ID] = i - return nil -} - -func (s *store) get(id string) (Image, error) { - s.lock.RLock() - defer s.lock.RUnlock() - digest, err := s.digestSet.Lookup(id) - if err != nil { - if err == digestset.ErrDigestNotFound { - err = storeutil.ErrNotExist - } - return Image{}, err - } - if i, ok := s.images[digest.String()]; ok { - return i, nil - } - return Image{}, storeutil.ErrNotExist -} - -func (s *store) delete(id, ref string) { - s.lock.Lock() - defer s.lock.Unlock() - digest, err := s.digestSet.Lookup(id) - if err != nil { - // Note: The idIndex.Delete and delete doesn't handle truncated index. - // So we need to return if there are error. - return - } - i, ok := s.images[digest.String()] - if !ok { - return - } - i.References = util.SubtractStringSlice(i.References, ref) - if len(i.References) != 0 { - s.images[digest.String()] = i - return - } - // Remove the image if it is not referenced any more. - s.digestSet.Remove(digest) // nolint: errcheck - delete(s.images, digest.String()) -} diff --git a/vendor/github.com/containerd/cri/pkg/store/label/label.go b/vendor/github.com/containerd/cri/pkg/store/label/label.go deleted file mode 100644 index c8c5ff924..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/label/label.go +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package label - -import ( - "sync" - - "github.com/opencontainers/selinux/go-selinux" -) - -type Store struct { - sync.Mutex - levels map[string]int - Releaser func(string) - Reserver func(string) -} - -func NewStore() *Store { - return &Store{ - levels: map[string]int{}, - Releaser: selinux.ReleaseLabel, - Reserver: selinux.ReserveLabel, - } -} - -func (s *Store) Reserve(label string) error { - s.Lock() - defer s.Unlock() - - context, err := selinux.NewContext(label) - if err != nil { - return err - } - - level := context["level"] - // no reason to count empty - if level == "" { - return nil - } - - if _, ok := s.levels[level]; !ok { - s.Reserver(label) - } - - s.levels[level]++ - return nil -} - -func (s *Store) Release(label string) { - s.Lock() - defer s.Unlock() - - context, err := selinux.NewContext(label) - if err != nil { - return - } - - level := context["level"] - if level == "" { - return - } - - count, ok := s.levels[level] - if !ok { - return - } - switch { - case count == 1: - s.Releaser(label) - delete(s.levels, level) - case count < 1: - delete(s.levels, level) - case count > 1: - s.levels[level] = count - 1 - } -} diff --git a/vendor/github.com/containerd/cri/pkg/store/sandbox/metadata.go b/vendor/github.com/containerd/cri/pkg/store/sandbox/metadata.go deleted file mode 100644 index eb3aa8e83..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/sandbox/metadata.go +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sandbox - -import ( - "encoding/json" - - cni "github.com/containerd/go-cni" - "github.com/pkg/errors" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// NOTE(random-liu): -// 1) Metadata is immutable after created. -// 2) Metadata is checkpointed as containerd container label. - -// metadataVersion is current version of sandbox metadata. -const metadataVersion = "v1" // nolint - -// versionedMetadata is the internal versioned sandbox metadata. -// nolint -type versionedMetadata struct { - // Version indicates the version of the versioned sandbox metadata. - Version string - // Metadata's type is metadataInternal. If not there will be a recursive call in MarshalJSON. - Metadata metadataInternal -} - -// metadataInternal is for internal use. -type metadataInternal Metadata - -// Metadata is the unversioned sandbox metadata. -type Metadata struct { - // ID is the sandbox id. - ID string - // Name is the sandbox name. - Name string - // Config is the CRI sandbox config. - Config *runtime.PodSandboxConfig - // NetNSPath is the network namespace used by the sandbox. - NetNSPath string - // IP of Pod if it is attached to non host network - IP string - // AdditionalIPs of the Pod if it is attached to non host network - AdditionalIPs []string - // RuntimeHandler is the runtime handler name of the pod. - RuntimeHandler string - // CNIresult resulting configuration for attached network namespace interfaces - CNIResult *cni.CNIResult - // ProcessLabel is the SELinux process label for the container - ProcessLabel string -} - -// MarshalJSON encodes Metadata into bytes in json format. -func (c *Metadata) MarshalJSON() ([]byte, error) { - return json.Marshal(&versionedMetadata{ - Version: metadataVersion, - Metadata: metadataInternal(*c), - }) -} - -// UnmarshalJSON decodes Metadata from bytes. -func (c *Metadata) UnmarshalJSON(data []byte) error { - versioned := &versionedMetadata{} - if err := json.Unmarshal(data, versioned); err != nil { - return err - } - // Handle old version after upgrade. - switch versioned.Version { - case metadataVersion: - *c = Metadata(versioned.Metadata) - return nil - } - return errors.Errorf("unsupported version: %q", versioned.Version) -} diff --git a/vendor/github.com/containerd/cri/pkg/store/sandbox/sandbox.go b/vendor/github.com/containerd/cri/pkg/store/sandbox/sandbox.go deleted file mode 100644 index 223e88369..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/sandbox/sandbox.go +++ /dev/null @@ -1,137 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sandbox - -import ( - "sync" - - "github.com/containerd/containerd" - "github.com/containerd/cri/pkg/store/label" - "github.com/docker/docker/pkg/truncindex" - - "github.com/containerd/cri/pkg/netns" - "github.com/containerd/cri/pkg/store" -) - -// Sandbox contains all resources associated with the sandbox. All methods to -// mutate the internal state are thread safe. -type Sandbox struct { - // Metadata is the metadata of the sandbox, it is immutable after created. - Metadata - // Status stores the status of the sandbox. - Status StatusStorage - // Container is the containerd sandbox container client. - Container containerd.Container - // CNI network namespace client. - // For hostnetwork pod, this is always nil; - // For non hostnetwork pod, this should never be nil. - NetNS *netns.NetNS - // StopCh is used to propagate the stop information of the sandbox. - *store.StopCh -} - -// NewSandbox creates an internally used sandbox type. This functions reminds -// the caller that a sandbox must have a status. -func NewSandbox(metadata Metadata, status Status) Sandbox { - s := Sandbox{ - Metadata: metadata, - Status: StoreStatus(status), - StopCh: store.NewStopCh(), - } - if status.State == StateNotReady { - s.Stop() - } - return s -} - -// Store stores all sandboxes. -type Store struct { - lock sync.RWMutex - sandboxes map[string]Sandbox - idIndex *truncindex.TruncIndex - labels *label.Store -} - -// NewStore creates a sandbox store. -func NewStore(labels *label.Store) *Store { - return &Store{ - sandboxes: make(map[string]Sandbox), - idIndex: truncindex.NewTruncIndex([]string{}), - labels: labels, - } -} - -// Add a sandbox into the store. -func (s *Store) Add(sb Sandbox) error { - s.lock.Lock() - defer s.lock.Unlock() - if _, ok := s.sandboxes[sb.ID]; ok { - return store.ErrAlreadyExist - } - if err := s.labels.Reserve(sb.ProcessLabel); err != nil { - return err - } - if err := s.idIndex.Add(sb.ID); err != nil { - return err - } - s.sandboxes[sb.ID] = sb - return nil -} - -// Get returns the sandbox with specified id. -// Returns store.ErrNotExist if the sandbox doesn't exist. -func (s *Store) Get(id string) (Sandbox, error) { - s.lock.RLock() - defer s.lock.RUnlock() - id, err := s.idIndex.Get(id) - if err != nil { - if err == truncindex.ErrNotExist { - err = store.ErrNotExist - } - return Sandbox{}, err - } - if sb, ok := s.sandboxes[id]; ok { - return sb, nil - } - return Sandbox{}, store.ErrNotExist -} - -// List lists all sandboxes. -func (s *Store) List() []Sandbox { - s.lock.RLock() - defer s.lock.RUnlock() - var sandboxes []Sandbox - for _, sb := range s.sandboxes { - sandboxes = append(sandboxes, sb) - } - return sandboxes -} - -// Delete deletes the sandbox with specified id. -func (s *Store) Delete(id string) { - s.lock.Lock() - defer s.lock.Unlock() - id, err := s.idIndex.Get(id) - if err != nil { - // Note: The idIndex.Delete and delete doesn't handle truncated index. - // So we need to return if there are error. - return - } - s.labels.Release(s.sandboxes[id].ProcessLabel) - s.idIndex.Delete(id) // nolint: errcheck - delete(s.sandboxes, id) -} diff --git a/vendor/github.com/containerd/cri/pkg/store/sandbox/status.go b/vendor/github.com/containerd/cri/pkg/store/sandbox/status.go deleted file mode 100644 index e9198eb97..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/sandbox/status.go +++ /dev/null @@ -1,151 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sandbox - -import ( - "strconv" - "sync" - "time" - - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// The sandbox state machine in the CRI plugin: -// + + -// | | -// | Create(Run) | Load -// | | -// Start | | -// (failed) | | -// +------------------+ +-----------+ -// | | | | -// | | | | -// | | | | -// | | Start(Run) | | -// | | | | -// | PortForward +----v----+ | | -// | +------+ | | | -// | | | READY <---------+ | -// | +------> | | | -// | +----+----+ | | -// | | | | -// | | Stop/Exit | | -// | | | | -// | +----v----+ | | -// | | <---------+ +----v----+ -// | | NOTREADY| | | -// | | <----------------+ UNKNOWN | -// | +----+----+ Stop | | -// | | +---------+ -// | | Remove -// | v -// +-------------> DELETED - -// State is the sandbox state we use in containerd/cri. -// It includes unknown, which is internal states not defined in CRI. -// The state mapping from internal states to CRI states: -// * ready -> ready -// * not ready -> not ready -// * unknown -> not ready -type State uint32 - -const ( - // StateReady is ready state, it means sandbox container - // is running. - StateReady State = iota - // StateNotReady is notready state, it ONLY means sandbox - // container is not running. - // StopPodSandbox should still be called for NOTREADY sandbox to - // cleanup resources other than sandbox container, e.g. network namespace. - // This is an assumption made in CRI. - StateNotReady - // StateUnknown is unknown state. Sandbox only goes - // into unknown state when its status fails to be loaded. - StateUnknown -) - -// String returns the string representation of the state -func (s State) String() string { - switch s { - case StateReady: - return runtime.PodSandboxState_SANDBOX_READY.String() - case StateNotReady: - return runtime.PodSandboxState_SANDBOX_NOTREADY.String() - case StateUnknown: - // PodSandboxState doesn't have an unknown state, but State does, so return a string using the same convention - return "SANDBOX_UNKNOWN" - default: - return "invalid sandbox state value: " + strconv.Itoa(int(s)) - } -} - -// Status is the status of a sandbox. -type Status struct { - // Pid is the init process id of the sandbox container. - Pid uint32 - // CreatedAt is the created timestamp. - CreatedAt time.Time - // State is the state of the sandbox. - State State -} - -// UpdateFunc is function used to update the sandbox status. If there -// is an error, the update will be rolled back. -type UpdateFunc func(Status) (Status, error) - -// StatusStorage manages the sandbox status. -// The status storage for sandbox is different from container status storage, -// because we don't checkpoint sandbox status. If we need checkpoint in the -// future, we should combine this with container status storage. -type StatusStorage interface { - // Get a sandbox status. - Get() Status - // Update the sandbox status. Note that the update MUST be applied - // in one transaction. - Update(UpdateFunc) error -} - -// StoreStatus creates the storage containing the passed in sandbox status with the -// specified id. -// The status MUST be created in one transaction. -func StoreStatus(status Status) StatusStorage { - return &statusStorage{status: status} -} - -type statusStorage struct { - sync.RWMutex - status Status -} - -// Get a copy of sandbox status. -func (s *statusStorage) Get() Status { - s.RLock() - defer s.RUnlock() - return s.status -} - -// Update the sandbox status. -func (s *statusStorage) Update(u UpdateFunc) error { - s.Lock() - defer s.Unlock() - newStatus, err := u(s.status) - if err != nil { - return err - } - s.status = newStatus - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/store/snapshot/snapshot.go b/vendor/github.com/containerd/cri/pkg/store/snapshot/snapshot.go deleted file mode 100644 index ce05f0e04..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/snapshot/snapshot.go +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package snapshot - -import ( - "sync" - - snapshot "github.com/containerd/containerd/snapshots" - - "github.com/containerd/cri/pkg/store" -) - -// Snapshot contains the information about the snapshot. -type Snapshot struct { - // Key is the key of the snapshot - Key string - // Kind is the kind of the snapshot (active, committed, view) - Kind snapshot.Kind - // Size is the size of the snapshot in bytes. - Size uint64 - // Inodes is the number of inodes used by the snapshot - Inodes uint64 - // Timestamp is latest update time (in nanoseconds) of the snapshot - // information. - Timestamp int64 -} - -// Store stores all snapshots. -type Store struct { - lock sync.RWMutex - snapshots map[string]Snapshot -} - -// NewStore creates a snapshot store. -func NewStore() *Store { - return &Store{snapshots: make(map[string]Snapshot)} -} - -// Add a snapshot into the store. -func (s *Store) Add(snapshot Snapshot) { - s.lock.Lock() - defer s.lock.Unlock() - s.snapshots[snapshot.Key] = snapshot -} - -// Get returns the snapshot with specified key. Returns store.ErrNotExist if the -// snapshot doesn't exist. -func (s *Store) Get(key string) (Snapshot, error) { - s.lock.RLock() - defer s.lock.RUnlock() - if sn, ok := s.snapshots[key]; ok { - return sn, nil - } - return Snapshot{}, store.ErrNotExist -} - -// List lists all snapshots. -func (s *Store) List() []Snapshot { - s.lock.RLock() - defer s.lock.RUnlock() - var snapshots []Snapshot - for _, sn := range s.snapshots { - snapshots = append(snapshots, sn) - } - return snapshots -} - -// Delete deletes the snapshot with specified key. -func (s *Store) Delete(key string) { - s.lock.Lock() - defer s.lock.Unlock() - delete(s.snapshots, key) -} diff --git a/vendor/github.com/containerd/cri/pkg/store/util.go b/vendor/github.com/containerd/cri/pkg/store/util.go deleted file mode 100644 index 73626b1af..000000000 --- a/vendor/github.com/containerd/cri/pkg/store/util.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package store - -import "sync" - -// StopCh is used to propagate the stop information of a container. -type StopCh struct { - ch chan struct{} - once sync.Once -} - -// NewStopCh creates a stop channel. The channel is open by default. -func NewStopCh() *StopCh { - return &StopCh{ch: make(chan struct{})} -} - -// Stop close stopCh of the container. -func (s *StopCh) Stop() { - s.once.Do(func() { - close(s.ch) - }) -} - -// Stopped return the stopCh of the container as a readonly channel. -func (s *StopCh) Stopped() <-chan struct{} { - return s.ch -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/errors.go b/vendor/github.com/containerd/cri/pkg/streaming/errors.go deleted file mode 100644 index 874064054..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/errors.go +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package streaming - -import ( - "net/http" - "strconv" - - "google.golang.org/grpc/codes" - grpcstatus "google.golang.org/grpc/status" -) - -// NewErrorStreamingDisabled creates an error for disabled streaming method. -func NewErrorStreamingDisabled(method string) error { - return grpcstatus.Errorf(codes.NotFound, "streaming method %s disabled", method) -} - -// NewErrorTooManyInFlight creates an error for exceeding the maximum number of in-flight requests. -func NewErrorTooManyInFlight() error { - return grpcstatus.Error(codes.ResourceExhausted, "maximum number of in-flight requests exceeded") -} - -// WriteError translates a CRI streaming error into an appropriate HTTP response. -func WriteError(err error, w http.ResponseWriter) error { - s, _ := grpcstatus.FromError(err) - var status int - switch s.Code() { - case codes.NotFound: - status = http.StatusNotFound - case codes.ResourceExhausted: - // We only expect to hit this if there is a DoS, so we just wait the full TTL. - // If this is ever hit in steady-state operations, consider increasing the maxInFlight requests, - // or plumbing through the time to next expiration. - w.Header().Set("Retry-After", strconv.Itoa(int(cacheTTL.Seconds()))) - status = http.StatusTooManyRequests - default: - status = http.StatusInternalServerError - } - w.WriteHeader(status) - _, writeErr := w.Write([]byte(err.Error())) - return writeErr -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/portforward/constants.go b/vendor/github.com/containerd/cri/pkg/streaming/portforward/constants.go deleted file mode 100644 index 217a0b114..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/portforward/constants.go +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package portforward contains server-side logic for handling port forwarding requests. -package portforward - -// ProtocolV1Name is the name of the subprotocol used for port forwarding. -const ProtocolV1Name = "portforward.k8s.io" - -// SupportedProtocols are the supported port forwarding protocols. -var SupportedProtocols = []string{ProtocolV1Name} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/portforward/httpstream.go b/vendor/github.com/containerd/cri/pkg/streaming/portforward/httpstream.go deleted file mode 100644 index f961cdb6f..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/portforward/httpstream.go +++ /dev/null @@ -1,315 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package portforward - -import ( - "errors" - "fmt" - "net/http" - "strconv" - "sync" - "time" - - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/httpstream" - "k8s.io/apimachinery/pkg/util/httpstream/spdy" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - - "k8s.io/klog/v2" -) - -func handleHTTPStreams(req *http.Request, w http.ResponseWriter, portForwarder PortForwarder, podName string, uid types.UID, supportedPortForwardProtocols []string, idleTimeout, streamCreationTimeout time.Duration) error { - _, err := httpstream.Handshake(req, w, supportedPortForwardProtocols) - // negotiated protocol isn't currently used server side, but could be in the future - if err != nil { - // Handshake writes the error to the client - return err - } - streamChan := make(chan httpstream.Stream, 1) - - klog.V(5).Infof("Upgrading port forward response") - upgrader := spdy.NewResponseUpgrader() - conn := upgrader.UpgradeResponse(w, req, httpStreamReceived(streamChan)) - if conn == nil { - return errors.New("unable to upgrade httpstream connection") - } - defer conn.Close() - - klog.V(5).Infof("(conn=%p) setting port forwarding streaming connection idle timeout to %v", conn, idleTimeout) - conn.SetIdleTimeout(idleTimeout) - - h := &httpStreamHandler{ - conn: conn, - streamChan: streamChan, - streamPairs: make(map[string]*httpStreamPair), - streamCreationTimeout: streamCreationTimeout, - pod: podName, - uid: uid, - forwarder: portForwarder, - } - h.run() - - return nil -} - -// httpStreamReceived is the httpstream.NewStreamHandler for port -// forward streams. It checks each stream's port and stream type headers, -// rejecting any streams that with missing or invalid values. Each valid -// stream is sent to the streams channel. -func httpStreamReceived(streams chan httpstream.Stream) func(httpstream.Stream, <-chan struct{}) error { - return func(stream httpstream.Stream, replySent <-chan struct{}) error { - // make sure it has a valid port header - portString := stream.Headers().Get(api.PortHeader) - if len(portString) == 0 { - return fmt.Errorf("%q header is required", api.PortHeader) - } - port, err := strconv.ParseUint(portString, 10, 16) - if err != nil { - return fmt.Errorf("unable to parse %q as a port: %v", portString, err) - } - if port < 1 { - return fmt.Errorf("port %q must be > 0", portString) - } - - // make sure it has a valid stream type header - streamType := stream.Headers().Get(api.StreamType) - if len(streamType) == 0 { - return fmt.Errorf("%q header is required", api.StreamType) - } - if streamType != api.StreamTypeError && streamType != api.StreamTypeData { - return fmt.Errorf("invalid stream type %q", streamType) - } - - streams <- stream - return nil - } -} - -// httpStreamHandler is capable of processing multiple port forward -// requests over a single httpstream.Connection. -type httpStreamHandler struct { - conn httpstream.Connection - streamChan chan httpstream.Stream - streamPairsLock sync.RWMutex - streamPairs map[string]*httpStreamPair - streamCreationTimeout time.Duration - pod string - uid types.UID - forwarder PortForwarder -} - -// getStreamPair returns a httpStreamPair for requestID. This creates a -// new pair if one does not yet exist for the requestID. The returned bool is -// true if the pair was created. -func (h *httpStreamHandler) getStreamPair(requestID string) (*httpStreamPair, bool) { - h.streamPairsLock.Lock() - defer h.streamPairsLock.Unlock() - - if p, ok := h.streamPairs[requestID]; ok { - klog.V(5).Infof("(conn=%p, request=%s) found existing stream pair", h.conn, requestID) - return p, false - } - - klog.V(5).Infof("(conn=%p, request=%s) creating new stream pair", h.conn, requestID) - - p := newPortForwardPair(requestID) - h.streamPairs[requestID] = p - - return p, true -} - -// monitorStreamPair waits for the pair to receive both its error and data -// streams, or for the timeout to expire (whichever happens first), and then -// removes the pair. -func (h *httpStreamHandler) monitorStreamPair(p *httpStreamPair, timeout <-chan time.Time) { - select { - case <-timeout: - err := fmt.Errorf("(conn=%v, request=%s) timed out waiting for streams", h.conn, p.requestID) - utilruntime.HandleError(err) - p.printError(err.Error()) - case <-p.complete: - klog.V(5).Infof("(conn=%v, request=%s) successfully received error and data streams", h.conn, p.requestID) - } - h.removeStreamPair(p.requestID) -} - -// removeStreamPair removes the stream pair identified by requestID from streamPairs. -func (h *httpStreamHandler) removeStreamPair(requestID string) { - h.streamPairsLock.Lock() - defer h.streamPairsLock.Unlock() - - delete(h.streamPairs, requestID) -} - -// requestID returns the request id for stream. -func (h *httpStreamHandler) requestID(stream httpstream.Stream) string { - requestID := stream.Headers().Get(api.PortForwardRequestIDHeader) - if len(requestID) == 0 { - klog.V(5).Infof("(conn=%p) stream received without %s header", h.conn, api.PortForwardRequestIDHeader) - // If we get here, it's because the connection came from an older client - // that isn't generating the request id header - // (https://github.com/kubernetes/kubernetes/blob/843134885e7e0b360eb5441e85b1410a8b1a7a0c/pkg/client/unversioned/portforward/portforward.go#L258-L287) - // - // This is a best-effort attempt at supporting older clients. - // - // When there aren't concurrent new forwarded connections, each connection - // will have a pair of streams (data, error), and the stream IDs will be - // consecutive odd numbers, e.g. 1 and 3 for the first connection. Convert - // the stream ID into a pseudo-request id by taking the stream type and - // using id = stream.Identifier() when the stream type is error, - // and id = stream.Identifier() - 2 when it's data. - // - // NOTE: this only works when there are not concurrent new streams from - // multiple forwarded connections; it's a best-effort attempt at supporting - // old clients that don't generate request ids. If there are concurrent - // new connections, it's possible that 1 connection gets streams whose IDs - // are not consecutive (e.g. 5 and 9 instead of 5 and 7). - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - requestID = strconv.Itoa(int(stream.Identifier())) - case api.StreamTypeData: - requestID = strconv.Itoa(int(stream.Identifier()) - 2) - } - - klog.V(5).Infof("(conn=%p) automatically assigning request ID=%q from stream type=%s, stream ID=%d", h.conn, requestID, streamType, stream.Identifier()) - } - return requestID -} - -// run is the main loop for the httpStreamHandler. It processes new -// streams, invoking portForward for each complete stream pair. The loop exits -// when the httpstream.Connection is closed. -func (h *httpStreamHandler) run() { - klog.V(5).Infof("(conn=%p) waiting for port forward streams", h.conn) -Loop: - for { - select { - case <-h.conn.CloseChan(): - klog.V(5).Infof("(conn=%p) upgraded connection closed", h.conn) - break Loop - case stream := <-h.streamChan: - requestID := h.requestID(stream) - streamType := stream.Headers().Get(api.StreamType) - klog.V(5).Infof("(conn=%p, request=%s) received new stream of type %s", h.conn, requestID, streamType) - - p, created := h.getStreamPair(requestID) - if created { - go h.monitorStreamPair(p, time.After(h.streamCreationTimeout)) - } - if complete, err := p.add(stream); err != nil { - msg := fmt.Sprintf("error processing stream for request %s: %v", requestID, err) - utilruntime.HandleError(errors.New(msg)) - p.printError(msg) - } else if complete { - go h.portForward(p) - } - } - } -} - -// portForward invokes the httpStreamHandler's forwarder.PortForward -// function for the given stream pair. -func (h *httpStreamHandler) portForward(p *httpStreamPair) { - defer p.dataStream.Close() - defer p.errorStream.Close() - - portString := p.dataStream.Headers().Get(api.PortHeader) - port, _ := strconv.ParseInt(portString, 10, 32) - - klog.V(5).Infof("(conn=%p, request=%s) invoking forwarder.PortForward for port %s", h.conn, p.requestID, portString) - err := h.forwarder.PortForward(h.pod, h.uid, int32(port), p.dataStream) - klog.V(5).Infof("(conn=%p, request=%s) done invoking forwarder.PortForward for port %s", h.conn, p.requestID, portString) - - if err != nil { - msg := fmt.Errorf("error forwarding port %d to pod %s, uid %v: %v", port, h.pod, h.uid, err) - utilruntime.HandleError(msg) - fmt.Fprint(p.errorStream, msg.Error()) - } -} - -// httpStreamPair represents the error and data streams for a port -// forwarding request. -type httpStreamPair struct { - lock sync.RWMutex - requestID string - dataStream httpstream.Stream - errorStream httpstream.Stream - complete chan struct{} -} - -// newPortForwardPair creates a new httpStreamPair. -func newPortForwardPair(requestID string) *httpStreamPair { - return &httpStreamPair{ - requestID: requestID, - complete: make(chan struct{}), - } -} - -// add adds the stream to the httpStreamPair. If the pair already -// contains a stream for the new stream's type, an error is returned. add -// returns true if both the data and error streams for this pair have been -// received. -func (p *httpStreamPair) add(stream httpstream.Stream) (bool, error) { - p.lock.Lock() - defer p.lock.Unlock() - - switch stream.Headers().Get(api.StreamType) { - case api.StreamTypeError: - if p.errorStream != nil { - return false, errors.New("error stream already assigned") - } - p.errorStream = stream - case api.StreamTypeData: - if p.dataStream != nil { - return false, errors.New("data stream already assigned") - } - p.dataStream = stream - } - - complete := p.errorStream != nil && p.dataStream != nil - if complete { - close(p.complete) - } - return complete, nil -} - -// printError writes s to p.errorStream if p.errorStream has been set. -func (p *httpStreamPair) printError(s string) { - p.lock.RLock() - defer p.lock.RUnlock() - if p.errorStream != nil { - fmt.Fprint(p.errorStream, s) - } -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/portforward/portforward.go b/vendor/github.com/containerd/cri/pkg/streaming/portforward/portforward.go deleted file mode 100644 index 89a39ea66..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/portforward/portforward.go +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package portforward - -import ( - "io" - "net/http" - "time" - - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apiserver/pkg/util/wsstream" -) - -// PortForwarder knows how to forward content from a data stream to/from a port -// in a pod. -type PortForwarder interface { - // PortForwarder copies data between a data stream and a port in a pod. - PortForward(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error -} - -// ServePortForward handles a port forwarding request. A single request is -// kept alive as long as the client is still alive and the connection has not -// been timed out due to idleness. This function handles multiple forwarded -// connections; i.e., multiple `curl http://localhost:8888/` requests will be -// handled by a single invocation of ServePortForward. -func ServePortForward(w http.ResponseWriter, req *http.Request, portForwarder PortForwarder, podName string, uid types.UID, portForwardOptions *V4Options, idleTimeout time.Duration, streamCreationTimeout time.Duration, supportedProtocols []string) { - var err error - if wsstream.IsWebSocketRequest(req) { - err = handleWebSocketStreams(req, w, portForwarder, podName, uid, portForwardOptions, supportedProtocols, idleTimeout, streamCreationTimeout) - } else { - err = handleHTTPStreams(req, w, portForwarder, podName, uid, supportedProtocols, idleTimeout, streamCreationTimeout) - } - - if err != nil { - runtime.HandleError(err) - return - } -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/portforward/websocket.go b/vendor/github.com/containerd/cri/pkg/streaming/portforward/websocket.go deleted file mode 100644 index 1b1c0151a..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/portforward/websocket.go +++ /dev/null @@ -1,213 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package portforward - -import ( - "encoding/binary" - "fmt" - "io" - "net/http" - "strconv" - "strings" - "sync" - "time" - - "k8s.io/klog/v2" - - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apiserver/pkg/server/httplog" - "k8s.io/apiserver/pkg/util/wsstream" -) - -const ( - dataChannel = iota - errorChannel - - v4BinaryWebsocketProtocol = "v4." + wsstream.ChannelWebSocketProtocol - v4Base64WebsocketProtocol = "v4." + wsstream.Base64ChannelWebSocketProtocol -) - -// V4Options contains details about which streams are required for port -// forwarding. -// All fields included in V4Options need to be expressed explicitly in the -// CRI (k8s.io/cri-api/pkg/apis/{version}/api.proto) PortForwardRequest. -type V4Options struct { - Ports []int32 -} - -// NewV4Options creates a new options from the Request. -func NewV4Options(req *http.Request) (*V4Options, error) { - if !wsstream.IsWebSocketRequest(req) { - return &V4Options{}, nil - } - - portStrings := req.URL.Query()[api.PortHeader] - if len(portStrings) == 0 { - return nil, fmt.Errorf("query parameter %q is required", api.PortHeader) - } - - ports := make([]int32, 0, len(portStrings)) - for _, portString := range portStrings { - if len(portString) == 0 { - return nil, fmt.Errorf("query parameter %q cannot be empty", api.PortHeader) - } - for _, p := range strings.Split(portString, ",") { - port, err := strconv.ParseUint(p, 10, 16) - if err != nil { - return nil, fmt.Errorf("unable to parse %q as a port: %v", portString, err) - } - if port < 1 { - return nil, fmt.Errorf("port %q must be > 0", portString) - } - ports = append(ports, int32(port)) - } - } - - return &V4Options{ - Ports: ports, - }, nil -} - -// BuildV4Options returns a V4Options based on the given information. -func BuildV4Options(ports []int32) (*V4Options, error) { - return &V4Options{Ports: ports}, nil -} - -// handleWebSocketStreams handles requests to forward ports to a pod via -// a PortForwarder. A pair of streams are created per port (DATA n, -// ERROR n+1). The associated port is written to each stream as a unsigned 16 -// bit integer in little endian format. -func handleWebSocketStreams(req *http.Request, w http.ResponseWriter, portForwarder PortForwarder, podName string, uid types.UID, opts *V4Options, supportedPortForwardProtocols []string, idleTimeout, streamCreationTimeout time.Duration) error { - channels := make([]wsstream.ChannelType, 0, len(opts.Ports)*2) - for i := 0; i < len(opts.Ports); i++ { - channels = append(channels, wsstream.ReadWriteChannel, wsstream.WriteChannel) - } - conn := wsstream.NewConn(map[string]wsstream.ChannelProtocolConfig{ - "": { - Binary: true, - Channels: channels, - }, - v4BinaryWebsocketProtocol: { - Binary: true, - Channels: channels, - }, - v4Base64WebsocketProtocol: { - Binary: false, - Channels: channels, - }, - }) - conn.SetIdleTimeout(idleTimeout) - _, streams, err := conn.Open(httplog.Unlogged(req, w), req) - if err != nil { - err = fmt.Errorf("unable to upgrade websocket connection: %v", err) - return err - } - defer conn.Close() - streamPairs := make([]*websocketStreamPair, len(opts.Ports)) - for i := range streamPairs { - streamPair := websocketStreamPair{ - port: opts.Ports[i], - dataStream: streams[i*2+dataChannel], - errorStream: streams[i*2+errorChannel], - } - streamPairs[i] = &streamPair - - portBytes := make([]byte, 2) - // port is always positive so conversion is allowable - binary.LittleEndian.PutUint16(portBytes, uint16(streamPair.port)) - streamPair.dataStream.Write(portBytes) - streamPair.errorStream.Write(portBytes) - } - h := &websocketStreamHandler{ - conn: conn, - streamPairs: streamPairs, - pod: podName, - uid: uid, - forwarder: portForwarder, - } - h.run() - - return nil -} - -// websocketStreamPair represents the error and data streams for a port -// forwarding request. -type websocketStreamPair struct { - port int32 - dataStream io.ReadWriteCloser - errorStream io.WriteCloser -} - -// websocketStreamHandler is capable of processing a single port forward -// request over a websocket connection -type websocketStreamHandler struct { - conn *wsstream.Conn - streamPairs []*websocketStreamPair - pod string - uid types.UID - forwarder PortForwarder -} - -// run invokes the websocketStreamHandler's forwarder.PortForward -// function for the given stream pair. -func (h *websocketStreamHandler) run() { - wg := sync.WaitGroup{} - wg.Add(len(h.streamPairs)) - - for _, pair := range h.streamPairs { - p := pair - go func() { - defer wg.Done() - h.portForward(p) - }() - } - - wg.Wait() -} - -func (h *websocketStreamHandler) portForward(p *websocketStreamPair) { - defer p.dataStream.Close() - defer p.errorStream.Close() - - klog.V(5).Infof("(conn=%p) invoking forwarder.PortForward for port %d", h.conn, p.port) - err := h.forwarder.PortForward(h.pod, h.uid, p.port, p.dataStream) - klog.V(5).Infof("(conn=%p) done invoking forwarder.PortForward for port %d", h.conn, p.port) - - if err != nil { - msg := fmt.Errorf("error forwarding port %d to pod %s, uid %v: %v", p.port, h.pod, h.uid, err) - runtime.HandleError(msg) - fmt.Fprint(p.errorStream, msg.Error()) - } -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/attach.go b/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/attach.go deleted file mode 100644 index 2b127bdf9..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/attach.go +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package remotecommand - -import ( - "fmt" - "io" - "net/http" - "time" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/tools/remotecommand" -) - -// Attacher knows how to attach to a running container in a pod. -type Attacher interface { - // AttachContainer attaches to the running container in the pod, copying data between in/out/err - // and the container's stdin/stdout/stderr. - AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error -} - -// ServeAttach handles requests to attach to a container. After creating/receiving the required -// streams, it delegates the actual attaching to attacher. -func ServeAttach(w http.ResponseWriter, req *http.Request, attacher Attacher, podName string, uid types.UID, container string, streamOpts *Options, idleTimeout, streamCreationTimeout time.Duration, supportedProtocols []string) { - ctx, ok := createStreams(req, w, streamOpts, supportedProtocols, idleTimeout, streamCreationTimeout) - if !ok { - // error is handled by createStreams - return - } - defer ctx.conn.Close() - - err := attacher.AttachContainer(podName, uid, container, ctx.stdinStream, ctx.stdoutStream, ctx.stderrStream, ctx.tty, ctx.resizeChan) - if err != nil { - err = fmt.Errorf("error attaching to container: %v", err) - runtime.HandleError(err) - ctx.writeStatus(apierrors.NewInternalError(err)) - } else { - ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusSuccess, - }}) - } -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/doc.go b/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/doc.go deleted file mode 100644 index 6034cdc8e..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/doc.go +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package remotecommand contains functions related to executing commands in and attaching to pods. -package remotecommand diff --git a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/exec.go b/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/exec.go deleted file mode 100644 index 5111521ba..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/exec.go +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package remotecommand - -import ( - "fmt" - "io" - "net/http" - "time" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/tools/remotecommand" - utilexec "k8s.io/utils/exec" -) - -// Executor knows how to execute a command in a container in a pod. -type Executor interface { - // ExecInContainer executes a command in a container in the pod, copying data - // between in/out/err and the container's stdin/stdout/stderr. - ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error -} - -// ServeExec handles requests to execute a command in a container. After -// creating/receiving the required streams, it delegates the actual execution -// to the executor. -func ServeExec(w http.ResponseWriter, req *http.Request, executor Executor, podName string, uid types.UID, container string, cmd []string, streamOpts *Options, idleTimeout, streamCreationTimeout time.Duration, supportedProtocols []string) { - ctx, ok := createStreams(req, w, streamOpts, supportedProtocols, idleTimeout, streamCreationTimeout) - if !ok { - // error is handled by createStreams - return - } - defer ctx.conn.Close() - - err := executor.ExecInContainer(podName, uid, container, cmd, ctx.stdinStream, ctx.stdoutStream, ctx.stderrStream, ctx.tty, ctx.resizeChan, 0) - if err != nil { - if exitErr, ok := err.(utilexec.ExitError); ok && exitErr.Exited() { - rc := exitErr.ExitStatus() - ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusFailure, - Reason: remotecommandconsts.NonZeroExitCodeReason, - Details: &metav1.StatusDetails{ - Causes: []metav1.StatusCause{ - { - Type: remotecommandconsts.ExitCodeCauseType, - Message: fmt.Sprintf("%d", rc), - }, - }, - }, - Message: fmt.Sprintf("command terminated with non-zero exit code: %v", exitErr), - }}) - } else { - err = fmt.Errorf("error executing command in container: %v", err) - runtime.HandleError(err) - ctx.writeStatus(apierrors.NewInternalError(err)) - } - } else { - ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusSuccess, - }}) - } -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/httpstream.go b/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/httpstream.go deleted file mode 100644 index 0417a1a9e..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/httpstream.go +++ /dev/null @@ -1,463 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package remotecommand - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "time" - - api "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/httpstream" - "k8s.io/apimachinery/pkg/util/httpstream/spdy" - remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apiserver/pkg/util/wsstream" - "k8s.io/client-go/tools/remotecommand" - - "k8s.io/klog/v2" -) - -// Options contains details about which streams are required for -// remote command execution. -type Options struct { - Stdin bool - Stdout bool - Stderr bool - TTY bool -} - -// NewOptions creates a new Options from the Request. -func NewOptions(req *http.Request) (*Options, error) { - tty := req.FormValue(api.ExecTTYParam) == "1" - stdin := req.FormValue(api.ExecStdinParam) == "1" - stdout := req.FormValue(api.ExecStdoutParam) == "1" - stderr := req.FormValue(api.ExecStderrParam) == "1" - if tty && stderr { - // TODO: make this an error before we reach this method - klog.V(4).Infof("Access to exec with tty and stderr is not supported, bypassing stderr") - stderr = false - } - - if !stdin && !stdout && !stderr { - return nil, fmt.Errorf("you must specify at least 1 of stdin, stdout, stderr") - } - - return &Options{ - Stdin: stdin, - Stdout: stdout, - Stderr: stderr, - TTY: tty, - }, nil -} - -// context contains the connection and streams used when -// forwarding an attach or execute session into a container. -type context struct { - conn io.Closer - stdinStream io.ReadCloser - stdoutStream io.WriteCloser - stderrStream io.WriteCloser - writeStatus func(status *apierrors.StatusError) error - resizeStream io.ReadCloser - resizeChan chan remotecommand.TerminalSize - tty bool -} - -// streamAndReply holds both a Stream and a channel that is closed when the stream's reply frame is -// enqueued. Consumers can wait for replySent to be closed prior to proceeding, to ensure that the -// replyFrame is enqueued before the connection's goaway frame is sent (e.g. if a stream was -// received and right after, the connection gets closed). -type streamAndReply struct { - httpstream.Stream - replySent <-chan struct{} -} - -// waitStreamReply waits until either replySent or stop is closed. If replySent is closed, it sends -// an empty struct to the notify channel. -func waitStreamReply(replySent <-chan struct{}, notify chan<- struct{}, stop <-chan struct{}) { - select { - case <-replySent: - notify <- struct{}{} - case <-stop: - } -} - -func createStreams(req *http.Request, w http.ResponseWriter, opts *Options, supportedStreamProtocols []string, idleTimeout, streamCreationTimeout time.Duration) (*context, bool) { - var ctx *context - var ok bool - if wsstream.IsWebSocketRequest(req) { - ctx, ok = createWebSocketStreams(req, w, opts, idleTimeout) - } else { - ctx, ok = createHTTPStreamStreams(req, w, opts, supportedStreamProtocols, idleTimeout, streamCreationTimeout) - } - if !ok { - return nil, false - } - - if ctx.resizeStream != nil { - ctx.resizeChan = make(chan remotecommand.TerminalSize) - go handleResizeEvents(ctx.resizeStream, ctx.resizeChan) - } - - return ctx, true -} - -func createHTTPStreamStreams(req *http.Request, w http.ResponseWriter, opts *Options, supportedStreamProtocols []string, idleTimeout, streamCreationTimeout time.Duration) (*context, bool) { - protocol, err := httpstream.Handshake(req, w, supportedStreamProtocols) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return nil, false - } - - streamCh := make(chan streamAndReply) - - upgrader := spdy.NewResponseUpgrader() - conn := upgrader.UpgradeResponse(w, req, func(stream httpstream.Stream, replySent <-chan struct{}) error { - streamCh <- streamAndReply{Stream: stream, replySent: replySent} - return nil - }) - // from this point on, we can no longer call methods on response - if conn == nil { - // The upgrader is responsible for notifying the client of any errors that - // occurred during upgrading. All we can do is return here at this point - // if we weren't successful in upgrading. - return nil, false - } - - conn.SetIdleTimeout(idleTimeout) - - var handler protocolHandler - switch protocol { - case remotecommandconsts.StreamProtocolV4Name: - handler = &v4ProtocolHandler{} - case remotecommandconsts.StreamProtocolV3Name: - handler = &v3ProtocolHandler{} - case remotecommandconsts.StreamProtocolV2Name: - handler = &v2ProtocolHandler{} - case "": - klog.V(4).Infof("Client did not request protocol negotiation. Falling back to %q", remotecommandconsts.StreamProtocolV1Name) - fallthrough - case remotecommandconsts.StreamProtocolV1Name: - handler = &v1ProtocolHandler{} - } - - // count the streams client asked for, starting with 1 - expectedStreams := 1 - if opts.Stdin { - expectedStreams++ - } - if opts.Stdout { - expectedStreams++ - } - if opts.Stderr { - expectedStreams++ - } - if opts.TTY && handler.supportsTerminalResizing() { - expectedStreams++ - } - - expired := time.NewTimer(streamCreationTimeout) - defer expired.Stop() - - ctx, err := handler.waitForStreams(streamCh, expectedStreams, expired.C) - if err != nil { - runtime.HandleError(err) - return nil, false - } - - ctx.conn = conn - ctx.tty = opts.TTY - - return ctx, true -} - -type protocolHandler interface { - // waitForStreams waits for the expected streams or a timeout, returning a - // remoteCommandContext if all the streams were received, or an error if not. - waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) - // supportsTerminalResizing returns true if the protocol handler supports terminal resizing - supportsTerminalResizing() bool -} - -// v4ProtocolHandler implements the V4 protocol version for streaming command execution. It only differs -// in from v3 in the error stream format using an json-marshaled metav1.Status which carries -// the process' exit code. -type v4ProtocolHandler struct{} - -func (*v4ProtocolHandler) waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) { - ctx := &context{} - receivedStreams := 0 - replyChan := make(chan struct{}) - stop := make(chan struct{}) - defer close(stop) -WaitForStreams: - for { - select { - case stream := <-streams: - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - ctx.writeStatus = v4WriteStatusFunc(stream) // write json errors - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdin: - ctx.stdinStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdout: - ctx.stdoutStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStderr: - ctx.stderrStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeResize: - ctx.resizeStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - default: - runtime.HandleError(fmt.Errorf("unexpected stream type: %q", streamType)) - } - case <-replyChan: - receivedStreams++ - if receivedStreams == expectedStreams { - break WaitForStreams - } - case <-expired: - // TODO find a way to return the error to the user. Maybe use a separate - // stream to report errors? - return nil, errors.New("timed out waiting for client to create streams") - } - } - - return ctx, nil -} - -// supportsTerminalResizing returns true because v4ProtocolHandler supports it -func (*v4ProtocolHandler) supportsTerminalResizing() bool { return true } - -// v3ProtocolHandler implements the V3 protocol version for streaming command execution. -type v3ProtocolHandler struct{} - -func (*v3ProtocolHandler) waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) { - ctx := &context{} - receivedStreams := 0 - replyChan := make(chan struct{}) - stop := make(chan struct{}) - defer close(stop) -WaitForStreams: - for { - select { - case stream := <-streams: - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - ctx.writeStatus = v1WriteStatusFunc(stream) - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdin: - ctx.stdinStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdout: - ctx.stdoutStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStderr: - ctx.stderrStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeResize: - ctx.resizeStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - default: - runtime.HandleError(fmt.Errorf("unexpected stream type: %q", streamType)) - } - case <-replyChan: - receivedStreams++ - if receivedStreams == expectedStreams { - break WaitForStreams - } - case <-expired: - // TODO find a way to return the error to the user. Maybe use a separate - // stream to report errors? - return nil, errors.New("timed out waiting for client to create streams") - } - } - - return ctx, nil -} - -// supportsTerminalResizing returns true because v3ProtocolHandler supports it -func (*v3ProtocolHandler) supportsTerminalResizing() bool { return true } - -// v2ProtocolHandler implements the V2 protocol version for streaming command execution. -type v2ProtocolHandler struct{} - -func (*v2ProtocolHandler) waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) { - ctx := &context{} - receivedStreams := 0 - replyChan := make(chan struct{}) - stop := make(chan struct{}) - defer close(stop) -WaitForStreams: - for { - select { - case stream := <-streams: - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - ctx.writeStatus = v1WriteStatusFunc(stream) - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdin: - ctx.stdinStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdout: - ctx.stdoutStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStderr: - ctx.stderrStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - default: - runtime.HandleError(fmt.Errorf("unexpected stream type: %q", streamType)) - } - case <-replyChan: - receivedStreams++ - if receivedStreams == expectedStreams { - break WaitForStreams - } - case <-expired: - // TODO find a way to return the error to the user. Maybe use a separate - // stream to report errors? - return nil, errors.New("timed out waiting for client to create streams") - } - } - - return ctx, nil -} - -// supportsTerminalResizing returns false because v2ProtocolHandler doesn't support it. -func (*v2ProtocolHandler) supportsTerminalResizing() bool { return false } - -// v1ProtocolHandler implements the V1 protocol version for streaming command execution. -type v1ProtocolHandler struct{} - -func (*v1ProtocolHandler) waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) { - ctx := &context{} - receivedStreams := 0 - replyChan := make(chan struct{}) - stop := make(chan struct{}) - defer close(stop) -WaitForStreams: - for { - select { - case stream := <-streams: - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - ctx.writeStatus = v1WriteStatusFunc(stream) - - // This defer statement shouldn't be here, but due to previous refactoring, it ended up in - // here. This is what 1.0.x kubelets do, so we're retaining that behavior. This is fixed in - // the v2ProtocolHandler. - defer stream.Reset() - - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdin: - ctx.stdinStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdout: - ctx.stdoutStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStderr: - ctx.stderrStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - default: - runtime.HandleError(fmt.Errorf("unexpected stream type: %q", streamType)) - } - case <-replyChan: - receivedStreams++ - if receivedStreams == expectedStreams { - break WaitForStreams - } - case <-expired: - // TODO find a way to return the error to the user. Maybe use a separate - // stream to report errors? - return nil, errors.New("timed out waiting for client to create streams") - } - } - - if ctx.stdinStream != nil { - ctx.stdinStream.Close() - } - - return ctx, nil -} - -// supportsTerminalResizing returns false because v1ProtocolHandler doesn't support it. -func (*v1ProtocolHandler) supportsTerminalResizing() bool { return false } - -func handleResizeEvents(stream io.Reader, channel chan<- remotecommand.TerminalSize) { - defer runtime.HandleCrash() - defer close(channel) - - decoder := json.NewDecoder(stream) - for { - size := remotecommand.TerminalSize{} - if err := decoder.Decode(&size); err != nil { - break - } - channel <- size - } -} - -func v1WriteStatusFunc(stream io.Writer) func(status *apierrors.StatusError) error { - return func(status *apierrors.StatusError) error { - if status.Status().Status == metav1.StatusSuccess { - return nil // send error messages - } - _, err := stream.Write([]byte(status.Error())) - return err - } -} - -// v4WriteStatusFunc returns a WriteStatusFunc that marshals a given api Status -// as json in the error channel. -func v4WriteStatusFunc(stream io.Writer) func(status *apierrors.StatusError) error { - return func(status *apierrors.StatusError) error { - bs, err := json.Marshal(status.Status()) - if err != nil { - return err - } - _, err = stream.Write(bs) - return err - } -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/websocket.go b/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/websocket.go deleted file mode 100644 index 99c0af7c3..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/remotecommand/websocket.go +++ /dev/null @@ -1,148 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package remotecommand - -import ( - "fmt" - "net/http" - "time" - - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apiserver/pkg/server/httplog" - "k8s.io/apiserver/pkg/util/wsstream" -) - -const ( - stdinChannel = iota - stdoutChannel - stderrChannel - errorChannel - resizeChannel - - preV4BinaryWebsocketProtocol = wsstream.ChannelWebSocketProtocol - preV4Base64WebsocketProtocol = wsstream.Base64ChannelWebSocketProtocol - v4BinaryWebsocketProtocol = "v4." + wsstream.ChannelWebSocketProtocol - v4Base64WebsocketProtocol = "v4." + wsstream.Base64ChannelWebSocketProtocol -) - -// createChannels returns the standard channel types for a shell connection (STDIN 0, STDOUT 1, STDERR 2) -// along with the approximate duplex value. It also creates the error (3) and resize (4) channels. -func createChannels(opts *Options) []wsstream.ChannelType { - // open the requested channels, and always open the error channel - channels := make([]wsstream.ChannelType, 5) - channels[stdinChannel] = readChannel(opts.Stdin) - channels[stdoutChannel] = writeChannel(opts.Stdout) - channels[stderrChannel] = writeChannel(opts.Stderr) - channels[errorChannel] = wsstream.WriteChannel - channels[resizeChannel] = wsstream.ReadChannel - return channels -} - -// readChannel returns wsstream.ReadChannel if real is true, or wsstream.IgnoreChannel. -func readChannel(real bool) wsstream.ChannelType { - if real { - return wsstream.ReadChannel - } - return wsstream.IgnoreChannel -} - -// writeChannel returns wsstream.WriteChannel if real is true, or wsstream.IgnoreChannel. -func writeChannel(real bool) wsstream.ChannelType { - if real { - return wsstream.WriteChannel - } - return wsstream.IgnoreChannel -} - -// createWebSocketStreams returns a context containing the websocket connection and -// streams needed to perform an exec or an attach. -func createWebSocketStreams(req *http.Request, w http.ResponseWriter, opts *Options, idleTimeout time.Duration) (*context, bool) { - channels := createChannels(opts) - conn := wsstream.NewConn(map[string]wsstream.ChannelProtocolConfig{ - "": { - Binary: true, - Channels: channels, - }, - preV4BinaryWebsocketProtocol: { - Binary: true, - Channels: channels, - }, - preV4Base64WebsocketProtocol: { - Binary: false, - Channels: channels, - }, - v4BinaryWebsocketProtocol: { - Binary: true, - Channels: channels, - }, - v4Base64WebsocketProtocol: { - Binary: false, - Channels: channels, - }, - }) - conn.SetIdleTimeout(idleTimeout) - negotiatedProtocol, streams, err := conn.Open(httplog.Unlogged(req, w), req) - if err != nil { - runtime.HandleError(fmt.Errorf("unable to upgrade websocket connection: %v", err)) - return nil, false - } - - // Send an empty message to the lowest writable channel to notify the client the connection is established - // TODO: make generic to SPDY and WebSockets and do it outside of this method? - switch { - case opts.Stdout: - streams[stdoutChannel].Write([]byte{}) - case opts.Stderr: - streams[stderrChannel].Write([]byte{}) - default: - streams[errorChannel].Write([]byte{}) - } - - ctx := &context{ - conn: conn, - stdinStream: streams[stdinChannel], - stdoutStream: streams[stdoutChannel], - stderrStream: streams[stderrChannel], - tty: opts.TTY, - resizeStream: streams[resizeChannel], - } - - switch negotiatedProtocol { - case v4BinaryWebsocketProtocol, v4Base64WebsocketProtocol: - ctx.writeStatus = v4WriteStatusFunc(streams[errorChannel]) - default: - ctx.writeStatus = v1WriteStatusFunc(streams[errorChannel]) - } - - return ctx, true -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/request_cache.go b/vendor/github.com/containerd/cri/pkg/streaming/request_cache.go deleted file mode 100644 index 36d6921f6..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/request_cache.go +++ /dev/null @@ -1,162 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package streaming - -import ( - "container/list" - "crypto/rand" - "encoding/base64" - "fmt" - "math" - "sync" - "time" - - "k8s.io/apimachinery/pkg/util/clock" -) - -var ( - // cacheTTL is the timeout after which tokens become invalid. - cacheTTL = 1 * time.Minute - // maxInFlight is the maximum number of in-flight requests to allow. - maxInFlight = 1000 - // tokenLen is the length of the random base64 encoded token identifying the request. - tokenLen = 8 -) - -// requestCache caches streaming (exec/attach/port-forward) requests and generates a single-use -// random token for their retrieval. The requestCache is used for building streaming URLs without -// the need to encode every request parameter in the URL. -type requestCache struct { - // clock is used to obtain the current time - clock clock.Clock - - // tokens maps the generate token to the request for fast retrieval. - tokens map[string]*list.Element - // ll maintains an age-ordered request list for faster garbage collection of expired requests. - ll *list.List - - lock sync.Mutex -} - -// Type representing an *ExecRequest, *AttachRequest, or *PortForwardRequest. -type request interface{} - -type cacheEntry struct { - token string - req request - expireTime time.Time -} - -func newRequestCache() *requestCache { - return &requestCache{ - clock: clock.RealClock{}, - ll: list.New(), - tokens: make(map[string]*list.Element), - } -} - -// Insert the given request into the cache and returns the token used for fetching it out. -func (c *requestCache) Insert(req request) (token string, err error) { - c.lock.Lock() - defer c.lock.Unlock() - - // Remove expired entries. - c.gc() - // If the cache is full, reject the request. - if c.ll.Len() == maxInFlight { - return "", NewErrorTooManyInFlight() - } - token, err = c.uniqueToken() - if err != nil { - return "", err - } - ele := c.ll.PushFront(&cacheEntry{token, req, c.clock.Now().Add(cacheTTL)}) - - c.tokens[token] = ele - return token, nil -} - -// Consume the token (remove it from the cache) and return the cached request, if found. -func (c *requestCache) Consume(token string) (req request, found bool) { - c.lock.Lock() - defer c.lock.Unlock() - ele, ok := c.tokens[token] - if !ok { - return nil, false - } - c.ll.Remove(ele) - delete(c.tokens, token) - - entry := ele.Value.(*cacheEntry) - if c.clock.Now().After(entry.expireTime) { - // Entry already expired. - return nil, false - } - return entry.req, true -} - -// uniqueToken generates a random URL-safe token and ensures uniqueness. -func (c *requestCache) uniqueToken() (string, error) { - const maxTries = 10 - // Number of bytes to be tokenLen when base64 encoded. - tokenSize := math.Ceil(float64(tokenLen) * 6 / 8) - rawToken := make([]byte, int(tokenSize)) - for i := 0; i < maxTries; i++ { - if _, err := rand.Read(rawToken); err != nil { - return "", err - } - encoded := base64.RawURLEncoding.EncodeToString(rawToken) - token := encoded[:tokenLen] - // If it's unique, return it. Otherwise retry. - if _, exists := c.tokens[encoded]; !exists { - return token, nil - } - } - return "", fmt.Errorf("failed to generate unique token") -} - -// Must be write-locked prior to calling. -func (c *requestCache) gc() { - now := c.clock.Now() - for c.ll.Len() > 0 { - oldest := c.ll.Back() - entry := oldest.Value.(*cacheEntry) - if !now.After(entry.expireTime) { - return - } - - // Oldest value is expired; remove it. - c.ll.Remove(oldest) - delete(c.tokens, entry.token) - } -} diff --git a/vendor/github.com/containerd/cri/pkg/streaming/server.go b/vendor/github.com/containerd/cri/pkg/streaming/server.go deleted file mode 100644 index 589c9a8ca..000000000 --- a/vendor/github.com/containerd/cri/pkg/streaming/server.go +++ /dev/null @@ -1,399 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package streaming - -import ( - "crypto/tls" - "errors" - "io" - "net" - "net/http" - "net/url" - "path" - "time" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - restful "github.com/emicklei/go-restful" - - "k8s.io/apimachinery/pkg/types" - remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" - "k8s.io/client-go/tools/remotecommand" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - - "github.com/containerd/cri/pkg/streaming/portforward" - remotecommandserver "github.com/containerd/cri/pkg/streaming/remotecommand" -) - -// Server is the library interface to serve the stream requests. -type Server interface { - http.Handler - - // Get the serving URL for the requests. - // Requests must not be nil. Responses may be nil iff an error is returned. - GetExec(*runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error) - GetAttach(req *runtimeapi.AttachRequest) (*runtimeapi.AttachResponse, error) - GetPortForward(*runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error) - - // Start the server. - // addr is the address to serve on (address:port) stayUp indicates whether the server should - // listen until Stop() is called, or automatically stop after all expected connections are - // closed. Calling Get{Exec,Attach,PortForward} increments the expected connection count. - // Function does not return until the server is stopped. - Start(stayUp bool) error - // Stop the server, and terminate any open connections. - Stop() error -} - -// Runtime is the interface to execute the commands and provide the streams. -type Runtime interface { - Exec(containerID string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error - Attach(containerID string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error - PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error -} - -// Config defines the options used for running the stream server. -type Config struct { - // The host:port address the server will listen on. - Addr string - // The optional base URL for constructing streaming URLs. If empty, the baseURL will be - // constructed from the serve address. - // Note that for port "0", the URL port will be set to actual port in use. - BaseURL *url.URL - - // How long to leave idle connections open for. - StreamIdleTimeout time.Duration - // How long to wait for clients to create streams. Only used for SPDY streaming. - StreamCreationTimeout time.Duration - - // The streaming protocols the server supports (understands and permits). See - // k8s.io/kubernetes/pkg/kubelet/server/remotecommand/constants.go for available protocols. - // Only used for SPDY streaming. - SupportedRemoteCommandProtocols []string - - // The streaming protocols the server supports (understands and permits). See - // k8s.io/kubernetes/pkg/kubelet/server/portforward/constants.go for available protocols. - // Only used for SPDY streaming. - SupportedPortForwardProtocols []string - - // The config for serving over TLS. If nil, TLS will not be used. - TLSConfig *tls.Config -} - -// DefaultConfig provides default values for server Config. The DefaultConfig is partial, so -// some fields like Addr must still be provided. -var DefaultConfig = Config{ - StreamIdleTimeout: 4 * time.Hour, - StreamCreationTimeout: remotecommandconsts.DefaultStreamCreationTimeout, - SupportedRemoteCommandProtocols: remotecommandconsts.SupportedStreamingProtocols, - SupportedPortForwardProtocols: portforward.SupportedProtocols, -} - -// NewServer creates a new Server for stream requests. -// TODO(tallclair): Add auth(n/z) interface & handling. -func NewServer(config Config, runtime Runtime) (Server, error) { - s := &server{ - config: config, - runtime: &criAdapter{runtime}, - cache: newRequestCache(), - } - - if s.config.BaseURL == nil { - s.config.BaseURL = &url.URL{ - Scheme: "http", - Host: s.config.Addr, - } - if s.config.TLSConfig != nil { - s.config.BaseURL.Scheme = "https" - } - } - - ws := &restful.WebService{} - endpoints := []struct { - path string - handler restful.RouteFunction - }{ - {"/exec/{token}", s.serveExec}, - {"/attach/{token}", s.serveAttach}, - {"/portforward/{token}", s.servePortForward}, - } - // If serving relative to a base path, set that here. - pathPrefix := path.Dir(s.config.BaseURL.Path) - for _, e := range endpoints { - for _, method := range []string{"GET", "POST"} { - ws.Route(ws. - Method(method). - Path(path.Join(pathPrefix, e.path)). - To(e.handler)) - } - } - handler := restful.NewContainer() - handler.Add(ws) - s.handler = handler - s.server = &http.Server{ - Addr: s.config.Addr, - Handler: s.handler, - TLSConfig: s.config.TLSConfig, - } - - return s, nil -} - -type server struct { - config Config - runtime *criAdapter - handler http.Handler - cache *requestCache - server *http.Server -} - -func validateExecRequest(req *runtimeapi.ExecRequest) error { - if req.ContainerId == "" { - return status.Errorf(codes.InvalidArgument, "missing required container_id") - } - if req.Tty && req.Stderr { - // If TTY is set, stderr cannot be true because multiplexing is not - // supported. - return status.Errorf(codes.InvalidArgument, "tty and stderr cannot both be true") - } - if !req.Stdin && !req.Stdout && !req.Stderr { - return status.Errorf(codes.InvalidArgument, "one of stdin, stdout, or stderr must be set") - } - return nil -} - -func (s *server) GetExec(req *runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error) { - if err := validateExecRequest(req); err != nil { - return nil, err - } - token, err := s.cache.Insert(req) - if err != nil { - return nil, err - } - return &runtimeapi.ExecResponse{ - Url: s.buildURL("exec", token), - }, nil -} - -func validateAttachRequest(req *runtimeapi.AttachRequest) error { - if req.ContainerId == "" { - return status.Errorf(codes.InvalidArgument, "missing required container_id") - } - if req.Tty && req.Stderr { - // If TTY is set, stderr cannot be true because multiplexing is not - // supported. - return status.Errorf(codes.InvalidArgument, "tty and stderr cannot both be true") - } - if !req.Stdin && !req.Stdout && !req.Stderr { - return status.Errorf(codes.InvalidArgument, "one of stdin, stdout, and stderr must be set") - } - return nil -} - -func (s *server) GetAttach(req *runtimeapi.AttachRequest) (*runtimeapi.AttachResponse, error) { - if err := validateAttachRequest(req); err != nil { - return nil, err - } - token, err := s.cache.Insert(req) - if err != nil { - return nil, err - } - return &runtimeapi.AttachResponse{ - Url: s.buildURL("attach", token), - }, nil -} - -func (s *server) GetPortForward(req *runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error) { - if req.PodSandboxId == "" { - return nil, status.Errorf(codes.InvalidArgument, "missing required pod_sandbox_id") - } - token, err := s.cache.Insert(req) - if err != nil { - return nil, err - } - return &runtimeapi.PortForwardResponse{ - Url: s.buildURL("portforward", token), - }, nil -} - -func (s *server) Start(stayUp bool) error { - if !stayUp { - // TODO(tallclair): Implement this. - return errors.New("stayUp=false is not yet implemented") - } - - listener, err := net.Listen("tcp", s.config.Addr) - if err != nil { - return err - } - // Use the actual address as baseURL host. This handles the "0" port case. - s.config.BaseURL.Host = listener.Addr().String() - if s.config.TLSConfig != nil { - return s.server.ServeTLS(listener, "", "") // Use certs from TLSConfig. - } - return s.server.Serve(listener) -} - -func (s *server) Stop() error { - return s.server.Close() -} - -func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { - s.handler.ServeHTTP(w, r) -} - -func (s *server) buildURL(method, token string) string { - return s.config.BaseURL.ResolveReference(&url.URL{ - Path: path.Join(method, token), - }).String() -} - -func (s *server) serveExec(req *restful.Request, resp *restful.Response) { - token := req.PathParameter("token") - cachedRequest, ok := s.cache.Consume(token) - if !ok { - http.NotFound(resp.ResponseWriter, req.Request) - return - } - exec, ok := cachedRequest.(*runtimeapi.ExecRequest) - if !ok { - http.NotFound(resp.ResponseWriter, req.Request) - return - } - - streamOpts := &remotecommandserver.Options{ - Stdin: exec.Stdin, - Stdout: exec.Stdout, - Stderr: exec.Stderr, - TTY: exec.Tty, - } - - remotecommandserver.ServeExec( - resp.ResponseWriter, - req.Request, - s.runtime, - "", // unused: podName - "", // unusued: podUID - exec.ContainerId, - exec.Cmd, - streamOpts, - s.config.StreamIdleTimeout, - s.config.StreamCreationTimeout, - s.config.SupportedRemoteCommandProtocols) -} - -func (s *server) serveAttach(req *restful.Request, resp *restful.Response) { - token := req.PathParameter("token") - cachedRequest, ok := s.cache.Consume(token) - if !ok { - http.NotFound(resp.ResponseWriter, req.Request) - return - } - attach, ok := cachedRequest.(*runtimeapi.AttachRequest) - if !ok { - http.NotFound(resp.ResponseWriter, req.Request) - return - } - - streamOpts := &remotecommandserver.Options{ - Stdin: attach.Stdin, - Stdout: attach.Stdout, - Stderr: attach.Stderr, - TTY: attach.Tty, - } - remotecommandserver.ServeAttach( - resp.ResponseWriter, - req.Request, - s.runtime, - "", // unused: podName - "", // unusued: podUID - attach.ContainerId, - streamOpts, - s.config.StreamIdleTimeout, - s.config.StreamCreationTimeout, - s.config.SupportedRemoteCommandProtocols) -} - -func (s *server) servePortForward(req *restful.Request, resp *restful.Response) { - token := req.PathParameter("token") - cachedRequest, ok := s.cache.Consume(token) - if !ok { - http.NotFound(resp.ResponseWriter, req.Request) - return - } - pf, ok := cachedRequest.(*runtimeapi.PortForwardRequest) - if !ok { - http.NotFound(resp.ResponseWriter, req.Request) - return - } - - portForwardOptions, err := portforward.BuildV4Options(pf.Port) - if err != nil { - resp.WriteError(http.StatusBadRequest, err) - return - } - - portforward.ServePortForward( - resp.ResponseWriter, - req.Request, - s.runtime, - pf.PodSandboxId, - "", // unused: podUID - portForwardOptions, - s.config.StreamIdleTimeout, - s.config.StreamCreationTimeout, - s.config.SupportedPortForwardProtocols) -} - -// criAdapter wraps the Runtime functions to conform to the remotecommand interfaces. -// The adapter binds the container ID to the container name argument, and the pod sandbox ID to the pod name. -type criAdapter struct { - Runtime -} - -var _ remotecommandserver.Executor = &criAdapter{} -var _ remotecommandserver.Attacher = &criAdapter{} -var _ portforward.PortForwarder = &criAdapter{} - -func (a *criAdapter) ExecInContainer(podName string, podUID types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - return a.Runtime.Exec(container, cmd, in, out, err, tty, resize) -} - -func (a *criAdapter) AttachContainer(podName string, podUID types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - return a.Runtime.Attach(container, in, out, err, tty, resize) -} - -func (a *criAdapter) PortForward(podName string, podUID types.UID, port int32, stream io.ReadWriteCloser) error { - return a.Runtime.PortForward(podName, port, stream) -} diff --git a/vendor/github.com/containerd/cri/pkg/util/deep_copy.go b/vendor/github.com/containerd/cri/pkg/util/deep_copy.go deleted file mode 100644 index d0e0bf37e..000000000 --- a/vendor/github.com/containerd/cri/pkg/util/deep_copy.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package util - -import ( - "encoding/json" - - "github.com/pkg/errors" -) - -// DeepCopy makes a deep copy from src into dst. -func DeepCopy(dst interface{}, src interface{}) error { - if dst == nil { - return errors.New("dst cannot be nil") - } - if src == nil { - return errors.New("src cannot be nil") - } - bytes, err := json.Marshal(src) - if err != nil { - return errors.Wrap(err, "unable to marshal src") - } - err = json.Unmarshal(bytes, dst) - if err != nil { - return errors.Wrap(err, "unable to unmarshal into dst") - } - return nil -} diff --git a/vendor/github.com/containerd/cri/pkg/util/id.go b/vendor/github.com/containerd/cri/pkg/util/id.go deleted file mode 100644 index 90f762ba7..000000000 --- a/vendor/github.com/containerd/cri/pkg/util/id.go +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package util - -import ( - "encoding/hex" - "math/rand" -) - -// GenerateID generates a random unique id. -func GenerateID() string { - b := make([]byte, 32) - rand.Read(b) - return hex.EncodeToString(b) -} diff --git a/vendor/github.com/containerd/cri/pkg/util/image.go b/vendor/github.com/containerd/cri/pkg/util/image.go deleted file mode 100644 index d3abcd31a..000000000 --- a/vendor/github.com/containerd/cri/pkg/util/image.go +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package util - -import ( - "github.com/containerd/containerd/reference/docker" -) - -// NormalizeImageRef normalizes the image reference following the docker convention. This is added -// mainly for backward compatibility. -// The reference returned can only be either tagged or digested. For reference contains both tag -// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@ -// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as -// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa. -// -// Deprecated: use github.com/containerd/containerd/reference/docker.ParseDockerRef() instead -func NormalizeImageRef(ref string) (docker.Named, error) { - return docker.ParseDockerRef(ref) -} diff --git a/vendor/github.com/containerd/cri/pkg/util/strings.go b/vendor/github.com/containerd/cri/pkg/util/strings.go deleted file mode 100644 index df1a5c91a..000000000 --- a/vendor/github.com/containerd/cri/pkg/util/strings.go +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package util - -import "strings" - -// InStringSlice checks whether a string is inside a string slice. -// Comparison is case insensitive. -func InStringSlice(ss []string, str string) bool { - for _, s := range ss { - if strings.EqualFold(s, str) { - return true - } - } - return false -} - -// SubtractStringSlice subtracts string from string slice. -// Comparison is case insensitive. -func SubtractStringSlice(ss []string, str string) []string { - var res []string - for _, s := range ss { - if strings.EqualFold(s, str) { - continue - } - res = append(res, s) - } - return res -} - -// MergeStringSlices merges 2 string slices into one and remove duplicated elements. -func MergeStringSlices(a []string, b []string) []string { - set := map[string]struct{}{} - for _, s := range a { - set[s] = struct{}{} - } - for _, s := range b { - set[s] = struct{}{} - } - var ss []string - for s := range set { - ss = append(ss, s) - } - return ss -} diff --git a/vendor/github.com/containerd/cri/vendor.conf b/vendor/github.com/containerd/cri/vendor.conf deleted file mode 100644 index 82139978f..000000000 --- a/vendor/github.com/containerd/cri/vendor.conf +++ /dev/null @@ -1,102 +0,0 @@ -# cri dependencies -github.com/docker/docker 4634ce647cf2ce2c6031129ccd109e557244986f -github.com/opencontainers/selinux v1.6.0 -github.com/tchap/go-patricia v2.2.6 -github.com/willf/bitset v1.1.11 - -# containerd dependencies -github.com/beorn7/perks v1.0.1 -github.com/BurntSushi/toml v0.3.1 -github.com/cespare/xxhash/v2 v2.1.1 -github.com/containerd/cgroups 318312a373405e5e91134d8063d04d59768a1bff -github.com/containerd/console v1.0.0 -github.com/containerd/containerd v1.4.0 -github.com/containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165 -github.com/containerd/fifo f15a3290365b9d2627d189e619ab4008e0069caf -github.com/containerd/go-runc 7016d3ce2328dd2cb1192b2076ebd565c4e8df0c -github.com/containerd/nri 0afc7f031eaf9c7d9c1a381b7ab5462e89c998fc -github.com/containerd/ttrpc v1.0.1 -github.com/containerd/typeurl v1.0.1 -github.com/coreos/go-systemd/v22 v22.1.0 -github.com/cpuguy83/go-md2man/v2 v2.0.0 -github.com/docker/go-events e31b211e4f1cd09aa76fe4ac244571fab96ae47f -github.com/docker/go-metrics v0.0.1 -github.com/docker/go-units v0.4.0 -github.com/godbus/dbus/v5 v5.0.3 -github.com/gogo/googleapis v1.3.2 -github.com/gogo/protobuf v1.3.1 -github.com/golang/protobuf v1.3.5 -github.com/google/uuid v1.1.1 -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 -github.com/hashicorp/errwrap v1.0.0 -github.com/hashicorp/go-multierror v1.0.0 -github.com/hashicorp/golang-lru v0.5.3 -github.com/imdario/mergo v0.3.7 -github.com/konsorten/go-windows-terminal-sequences v1.0.3 -github.com/matttproud/golang_protobuf_extensions v1.0.1 -github.com/Microsoft/go-winio v0.4.14 -github.com/Microsoft/hcsshim v0.8.9 -github.com/opencontainers/go-digest v1.0.0 -github.com/opencontainers/image-spec v1.0.1 -github.com/opencontainers/runc v1.0.0-rc92 -github.com/opencontainers/runtime-spec 4d89ac9fbff6c455f46a5bb59c6b1bb7184a5e43 # v1.0.3-0.20200728170252-4d89ac9fbff6 -github.com/pkg/errors v0.9.1 -github.com/prometheus/client_golang v1.6.0 -github.com/prometheus/client_model v0.2.0 -github.com/prometheus/common v0.9.1 -github.com/prometheus/procfs v0.0.11 -github.com/russross/blackfriday/v2 v2.0.1 -github.com/shurcooL/sanitized_anchor_name v1.0.0 -github.com/sirupsen/logrus v1.6.0 -github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2 -github.com/urfave/cli v1.22.1 # NOTE: urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092 -go.etcd.io/bbolt v1.3.5 -go.opencensus.io v0.22.0 -golang.org/x/net ab34263943818b32f575efc978a3d24e80b04bd7 -golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e -golang.org/x/sys ed371f2e16b4b305ee99df548828de367527b76b -golang.org/x/text v0.3.3 -google.golang.org/genproto e50cd9704f63023d62cd06a1994b98227fc4d21a -google.golang.org/grpc v1.27.1 - -# cgroups dependencies -github.com/cilium/ebpf 1c8d4c9ef7759622653a1d319284a44652333b28 - -# kubernetes dependencies -github.com/davecgh/go-spew v1.1.1 -github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 -github.com/emicklei/go-restful v2.9.5 -github.com/go-logr/logr v0.2.0 -github.com/google/gofuzz v1.1.0 -github.com/json-iterator/go v1.1.10 -github.com/modern-go/concurrent 1.0.3 -github.com/modern-go/reflect2 v1.0.1 -github.com/pmezard/go-difflib v1.0.0 -github.com/stretchr/testify v1.4.0 -golang.org/x/crypto 75b288015ac94e66e3d6715fb68a9b41bf046ec2 -golang.org/x/oauth2 858c2ad4c8b6c5d10852cb89079f6ca1c7309787 -golang.org/x/time 555d28b269f0569763d25dbe1a237ae74c6bcc82 -gopkg.in/inf.v0 v0.9.1 -gopkg.in/yaml.v2 v2.2.8 -k8s.io/api v0.19.0-rc.4 -k8s.io/apiserver v0.19.0-rc.4 -k8s.io/apimachinery v0.19.0-rc.4 -k8s.io/client-go v0.19.0-rc.4 -k8s.io/component-base v0.19.0-rc.4 -k8s.io/cri-api v0.19.0-rc.4 -k8s.io/klog/v2 v2.2.0 -k8s.io/utils 2df71ebbae66f39338aed4cd0bb82d2212ee33cc -sigs.k8s.io/structured-merge-diff/v3 v3.0.0 -sigs.k8s.io/yaml v1.2.0 - -# cni dependencies -github.com/containerd/go-cni v1.0.1 -github.com/containernetworking/cni v0.8.0 -github.com/containernetworking/plugins v0.8.6 -github.com/fsnotify/fsnotify v1.4.9 - -# image decrypt depedencies -github.com/containerd/imgcrypt v1.0.1 -github.com/containers/ocicrypt v1.0.1 -github.com/fullsailor/pkcs7 8306686428a5fe132eac8cb7c4848af725098bd4 -gopkg.in/square/go-jose.v2 v2.3.1 diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE new file mode 100644 index 000000000..c67dad612 --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + The names of its contributors may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pmezard/go-difflib/README.md b/vendor/github.com/pmezard/go-difflib/README.md new file mode 100644 index 000000000..e87f307ed --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/README.md @@ -0,0 +1,50 @@ +go-difflib +========== + +[![Build Status](https://travis-ci.org/pmezard/go-difflib.png?branch=master)](https://travis-ci.org/pmezard/go-difflib) +[![GoDoc](https://godoc.org/github.com/pmezard/go-difflib/difflib?status.svg)](https://godoc.org/github.com/pmezard/go-difflib/difflib) + +Go-difflib is a partial port of python 3 difflib package. Its main goal +was to make unified and context diff available in pure Go, mostly for +testing purposes. + +The following class and functions (and related tests) have be ported: + +* `SequenceMatcher` +* `unified_diff()` +* `context_diff()` + +## Installation + +```bash +$ go get github.com/pmezard/go-difflib/difflib +``` + +### Quick Start + +Diffs are configured with Unified (or ContextDiff) structures, and can +be output to an io.Writer or returned as a string. + +```Go +diff := UnifiedDiff{ + A: difflib.SplitLines("foo\nbar\n"), + B: difflib.SplitLines("foo\nbaz\n"), + FromFile: "Original", + ToFile: "Current", + Context: 3, +} +text, _ := GetUnifiedDiffString(diff) +fmt.Printf(text) +``` + +would output: + +``` +--- Original ++++ Current +@@ -1,3 +1,3 @@ + foo +-bar ++baz +``` + diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go new file mode 100644 index 000000000..003e99fad --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go @@ -0,0 +1,772 @@ +// Package difflib is a partial port of Python difflib module. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// The following class and functions have been ported: +// +// - SequenceMatcher +// +// - unified_diff +// +// - context_diff +// +// Getting unified diffs was the main goal of the port. Keep in mind this code +// is mostly suitable to output text differences in a human friendly way, there +// are no guarantees generated diffs are consumable by patch(1). +package difflib + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

" lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +func NewMatcherWithJunk(a, b []string, autoJunk bool, + isJunk func(string) bool) *SequenceMatcher { + + m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} + m.SetSeqs(a, b) + return &m +} + +// Set two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// Set the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// Set the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s, _ := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s, _ := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s, _ := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// and for all (i',j',k') meeting those conditions, +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// Return list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// Return list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// Isolate change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n)}) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} + +// Return a measure of the sequences' similarity (float in [0,1]). +// +// Where T is the total number of elements in both sequences, and +// M is the number of matches, this is 2.0*M / T. +// Note that this is 1 if the sequences are identical, and 0 if +// they have nothing in common. +// +// .Ratio() is expensive to compute if you haven't already computed +// .GetMatchingBlocks() or .GetOpCodes(), in which case you may +// want to try .QuickRatio() or .RealQuickRation() first to get an +// upper bound. +func (m *SequenceMatcher) Ratio() float64 { + matches := 0 + for _, m := range m.GetMatchingBlocks() { + matches += m.Size + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() relatively quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute. +func (m *SequenceMatcher) QuickRatio() float64 { + // viewing a and b as multisets, set matches to the cardinality + // of their intersection; this counts the number of matches + // without regard to order, so is clearly an upper bound + if m.fullBCount == nil { + m.fullBCount = map[string]int{} + for _, s := range m.b { + m.fullBCount[s] = m.fullBCount[s] + 1 + } + } + + // avail[x] is the number of times x appears in 'b' less the + // number of times we've seen it in 'a' so far ... kinda + avail := map[string]int{} + matches := 0 + for _, s := range m.a { + n, ok := avail[s] + if !ok { + n = m.fullBCount[s] + } + avail[s] = n - 1 + if n > 0 { + matches += 1 + } + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() very quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute than either .Ratio() or .QuickRatio(). +func (m *SequenceMatcher) RealQuickRatio() float64 { + la, lb := len(m.a), len(m.b) + return calculateRatio(min(la, lb), la+lb) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +// Unified diff parameters +type UnifiedDiff struct { + A []string // First sequence lines + FromFile string // First file name + FromDate string // First file time + B []string // Second sequence lines + ToFile string // Second file name + ToDate string // Second file time + Eol string // Headers end of line, defaults to LF + Context int // Number of context lines +} + +// Compare two sequences of lines; generate the delta as a unified diff. +// +// Unified diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by 'n' which +// defaults to three. +// +// By default, the diff control lines (those with ---, +++, or @@) are +// created with a trailing newline. This is helpful so that inputs +// created from file.readlines() result in diffs that are suitable for +// file.writelines() since both the inputs and outputs have trailing +// newlines. +// +// For inputs that do not have trailing newlines, set the lineterm +// argument to "" so that the output will be uniformly newline free. +// +// The unidiff format normally has a header for filenames and modification +// times. Any or all of these may be specified using strings for +// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// The modification times are normally expressed in the ISO 8601 format. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + wf := func(format string, args ...interface{}) error { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + return err + } + ws := func(s string) error { + _, err := buf.WriteString(s) + return err + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } + } + } + first, last := g[0], g[len(g)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + return err + } + for _, c := range g { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + if c.Tag == 'e' { + for _, line := range diff.A[i1:i2] { + if err := ws(" " + line); err != nil { + return err + } + } + continue + } + if c.Tag == 'r' || c.Tag == 'd' { + for _, line := range diff.A[i1:i2] { + if err := ws("-" + line); err != nil { + return err + } + } + } + if c.Tag == 'r' || c.Tag == 'i' { + for _, line := range diff.B[j1:j2] { + if err := ws("+" + line); err != nil { + return err + } + } + } + } + } + return nil +} + +// Like WriteUnifiedDiff but returns the diff a string. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteUnifiedDiff(w, diff) + return string(w.Bytes()), err +} + +// Convert range to the "ed" format. +func formatRangeContext(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + if length <= 1 { + return fmt.Sprintf("%d", beginning) + } + return fmt.Sprintf("%d,%d", beginning, beginning+length-1) +} + +type ContextDiff UnifiedDiff + +// Compare two sequences of lines; generate the delta as a context diff. +// +// Context diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by diff.Context +// which defaults to three. +// +// By default, the diff control lines (those with *** or ---) are +// created with a trailing newline. +// +// For inputs that do not have trailing newlines, set the diff.Eol +// argument to "" so that the output will be uniformly newline free. +// +// The context diff format normally has a header for filenames and +// modification times. Any or all of these may be specified using +// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. +// The modification times are normally expressed in the ISO 8601 format. +// If not specified, the strings default to blanks. +func WriteContextDiff(writer io.Writer, diff ContextDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + var diffErr error + wf := func(format string, args ...interface{}) { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + if diffErr == nil && err != nil { + diffErr = err + } + } + ws := func(s string) { + _, err := buf.WriteString(s) + if diffErr == nil && err != nil { + diffErr = err + } + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + prefix := map[byte]string{ + 'i': "+ ", + 'd': "- ", + 'r': "! ", + 'e': " ", + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) + wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) + } + } + + first, last := g[0], g[len(g)-1] + ws("***************" + diff.Eol) + + range1 := formatRangeContext(first.I1, last.I2) + wf("*** %s ****%s", range1, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'd' { + for _, cc := range g { + if cc.Tag == 'i' { + continue + } + for _, line := range diff.A[cc.I1:cc.I2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + + range2 := formatRangeContext(first.J1, last.J2) + wf("--- %s ----%s", range2, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'i' { + for _, cc := range g { + if cc.Tag == 'd' { + continue + } + for _, line := range diff.B[cc.J1:cc.J2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + } + return diffErr +} + +// Like WriteContextDiff but returns the diff a string. +func GetContextDiffString(diff ContextDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteContextDiff(w, diff) + return string(w.Bytes()), err +} + +// Split a string on "\n" while preserving them. The output can be used +// as input for UnifiedDiff and ContextDiff structures. +func SplitLines(s string) []string { + lines := strings.SplitAfter(s, "\n") + lines[len(lines)-1] += "\n" + return lines +} diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE new file mode 100644 index 000000000..f38ec5956 --- /dev/null +++ b/vendor/github.com/stretchr/testify/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/README.md b/vendor/github.com/stretchr/testify/README.md new file mode 100644 index 000000000..ef0197e8a --- /dev/null +++ b/vendor/github.com/stretchr/testify/README.md @@ -0,0 +1,342 @@ +Testify - Thou Shalt Write Tests +================================ + +[![Build Status](https://travis-ci.org/stretchr/testify.svg)](https://travis-ci.org/stretchr/testify) [![Go Report Card](https://goreportcard.com/badge/github.com/stretchr/testify)](https://goreportcard.com/report/github.com/stretchr/testify) [![GoDoc](https://godoc.org/github.com/stretchr/testify?status.svg)](https://godoc.org/github.com/stretchr/testify) + +Go code (golang) set of packages that provide many tools for testifying that your code will behave as you intend. + +Features include: + + * [Easy assertions](#assert-package) + * [Mocking](#mock-package) + * [Testing suite interfaces and functions](#suite-package) + +Get started: + + * Install testify with [one line of code](#installation), or [update it with another](#staying-up-to-date) + * For an introduction to writing test code in Go, see http://golang.org/doc/code.html#Testing + * Check out the API Documentation http://godoc.org/github.com/stretchr/testify + * To make your testing life easier, check out our other project, [gorc](http://github.com/stretchr/gorc) + * A little about [Test-Driven Development (TDD)](http://en.wikipedia.org/wiki/Test-driven_development) + + + +[`assert`](http://godoc.org/github.com/stretchr/testify/assert "API documentation") package +------------------------------------------------------------------------------------------- + +The `assert` package provides some helpful methods that allow you to write better test code in Go. + + * Prints friendly, easy to read failure descriptions + * Allows for very readable code + * Optionally annotate each assertion with a message + +See it in action: + +```go +package yours + +import ( + "testing" + "github.com/stretchr/testify/assert" +) + +func TestSomething(t *testing.T) { + + // assert equality + assert.Equal(t, 123, 123, "they should be equal") + + // assert inequality + assert.NotEqual(t, 123, 456, "they should not be equal") + + // assert for nil (good for errors) + assert.Nil(t, object) + + // assert for not nil (good when you expect something) + if assert.NotNil(t, object) { + + // now we know that object isn't nil, we are safe to make + // further assertions without causing any errors + assert.Equal(t, "Something", object.Value) + + } + +} +``` + + * Every assert func takes the `testing.T` object as the first argument. This is how it writes the errors out through the normal `go test` capabilities. + * Every assert func returns a bool indicating whether the assertion was successful or not, this is useful for if you want to go on making further assertions under certain conditions. + +if you assert many times, use the below: + +```go +package yours + +import ( + "testing" + "github.com/stretchr/testify/assert" +) + +func TestSomething(t *testing.T) { + assert := assert.New(t) + + // assert equality + assert.Equal(123, 123, "they should be equal") + + // assert inequality + assert.NotEqual(123, 456, "they should not be equal") + + // assert for nil (good for errors) + assert.Nil(object) + + // assert for not nil (good when you expect something) + if assert.NotNil(object) { + + // now we know that object isn't nil, we are safe to make + // further assertions without causing any errors + assert.Equal("Something", object.Value) + } +} +``` + +[`require`](http://godoc.org/github.com/stretchr/testify/require "API documentation") package +--------------------------------------------------------------------------------------------- + +The `require` package provides same global functions as the `assert` package, but instead of returning a boolean result they terminate current test. + +See [t.FailNow](http://golang.org/pkg/testing/#T.FailNow) for details. + +[`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package +---------------------------------------------------------------------------------------- + +The `mock` package provides a mechanism for easily writing mock objects that can be used in place of real objects when writing test code. + +An example test function that tests a piece of code that relies on an external object `testObj`, can setup expectations (testify) and assert that they indeed happened: + +```go +package yours + +import ( + "testing" + "github.com/stretchr/testify/mock" +) + +/* + Test objects +*/ + +// MyMockedObject is a mocked object that implements an interface +// that describes an object that the code I am testing relies on. +type MyMockedObject struct{ + mock.Mock +} + +// DoSomething is a method on MyMockedObject that implements some interface +// and just records the activity, and returns what the Mock object tells it to. +// +// In the real object, this method would do something useful, but since this +// is a mocked object - we're just going to stub it out. +// +// NOTE: This method is not being tested here, code that uses this object is. +func (m *MyMockedObject) DoSomething(number int) (bool, error) { + + args := m.Called(number) + return args.Bool(0), args.Error(1) + +} + +/* + Actual test functions +*/ + +// TestSomething is an example of how to use our test object to +// make assertions about some target code we are testing. +func TestSomething(t *testing.T) { + + // create an instance of our test object + testObj := new(MyMockedObject) + + // setup expectations + testObj.On("DoSomething", 123).Return(true, nil) + + // call the code we are testing + targetFuncThatDoesSomethingWithObj(testObj) + + // assert that the expectations were met + testObj.AssertExpectations(t) + + +} + +// TestSomethingElse is a second example of how to use our test object to +// make assertions about some target code we are testing. +// This time using a placeholder. Placeholders might be used when the +// data being passed in is normally dynamically generated and cannot be +// predicted beforehand (eg. containing hashes that are time sensitive) +func TestSomethingElse(t *testing.T) { + + // create an instance of our test object + testObj := new(MyMockedObject) + + // setup expectations with a placeholder in the argument list + testObj.On("DoSomething", mock.Anything).Return(true, nil) + + // call the code we are testing + targetFuncThatDoesSomethingWithObj(testObj) + + // assert that the expectations were met + testObj.AssertExpectations(t) + + +} +``` + +For more information on how to write mock code, check out the [API documentation for the `mock` package](http://godoc.org/github.com/stretchr/testify/mock). + +You can use the [mockery tool](http://github.com/vektra/mockery) to autogenerate the mock code against an interface as well, making using mocks much quicker. + +[`suite`](http://godoc.org/github.com/stretchr/testify/suite "API documentation") package +----------------------------------------------------------------------------------------- + +The `suite` package provides functionality that you might be used to from more common object oriented languages. With it, you can build a testing suite as a struct, build setup/teardown methods and testing methods on your struct, and run them with 'go test' as per normal. + +An example suite is shown below: + +```go +// Basic imports +import ( + "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +// Define the suite, and absorb the built-in basic suite +// functionality from testify - including a T() method which +// returns the current testing context +type ExampleTestSuite struct { + suite.Suite + VariableThatShouldStartAtFive int +} + +// Make sure that VariableThatShouldStartAtFive is set to five +// before each test +func (suite *ExampleTestSuite) SetupTest() { + suite.VariableThatShouldStartAtFive = 5 +} + +// All methods that begin with "Test" are run as tests within a +// suite. +func (suite *ExampleTestSuite) TestExample() { + assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestExampleTestSuite(t *testing.T) { + suite.Run(t, new(ExampleTestSuite)) +} +``` + +For a more complete example, using all of the functionality provided by the suite package, look at our [example testing suite](https://github.com/stretchr/testify/blob/master/suite/suite_test.go) + +For more information on writing suites, check out the [API documentation for the `suite` package](http://godoc.org/github.com/stretchr/testify/suite). + +`Suite` object has assertion methods: + +```go +// Basic imports +import ( + "testing" + "github.com/stretchr/testify/suite" +) + +// Define the suite, and absorb the built-in basic suite +// functionality from testify - including assertion methods. +type ExampleTestSuite struct { + suite.Suite + VariableThatShouldStartAtFive int +} + +// Make sure that VariableThatShouldStartAtFive is set to five +// before each test +func (suite *ExampleTestSuite) SetupTest() { + suite.VariableThatShouldStartAtFive = 5 +} + +// All methods that begin with "Test" are run as tests within a +// suite. +func (suite *ExampleTestSuite) TestExample() { + suite.Equal(suite.VariableThatShouldStartAtFive, 5) +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestExampleTestSuite(t *testing.T) { + suite.Run(t, new(ExampleTestSuite)) +} +``` + +------ + +Installation +============ + +To install Testify, use `go get`: + + go get github.com/stretchr/testify + +This will then make the following packages available to you: + + github.com/stretchr/testify/assert + github.com/stretchr/testify/require + github.com/stretchr/testify/mock + github.com/stretchr/testify/suite + github.com/stretchr/testify/http (deprecated) + +Import the `testify/assert` package into your code using this template: + +```go +package yours + +import ( + "testing" + "github.com/stretchr/testify/assert" +) + +func TestSomething(t *testing.T) { + + assert.True(t, true, "True is true!") + +} +``` + +------ + +Staying up to date +================== + +To update Testify to the latest version, use `go get -u github.com/stretchr/testify`. + +------ + +Supported go versions +================== + +We support the three major Go versions, which are 1.9, 1.10, and 1.11 at the moment. + +------ + +Contributing +============ + +Please feel free to submit issues, fork the repository and send pull requests! + +When submitting an issue, we ask that you please include a complete test function that demonstrates the issue. Extra credit for those using Testify to write the test code that demonstrates it. + +Code generation is used. Look for `CODE GENERATED AUTOMATICALLY` at the top of some files. Run `go generate ./...` to update generated files. + +------ + +License +======= + +This project is licensed under the terms of the MIT license. diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go new file mode 100644 index 000000000..e0364e9e7 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -0,0 +1,566 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Conditionf uses a Comparison to assert a complex condition. +func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Condition(t, comp, append([]interface{}{msg}, args...)...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") +// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") +// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") +func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Contains(t, s, contains, append([]interface{}{msg}, args...)...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return DirExists(t, path, append([]interface{}{msg}, args...)...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Emptyf(t, obj, "error message %s", "formatted") +func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Empty(t, object, append([]interface{}{msg}, args...)...) +} + +// Equalf asserts that two objects are equal. +// +// assert.Equalf(t, 123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") +func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) +func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Errorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Error(t, err, append([]interface{}{msg}, args...)...) +} + +// Eventuallyf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) +func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Failf reports a failure through +func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) +} + +// FailNowf fails test +func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) +} + +// Falsef asserts that the specified value is false. +// +// assert.Falsef(t, myBool, "error message %s", "formatted") +func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return False(t, value, append([]interface{}{msg}, args...)...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return FileExists(t, path, append([]interface{}{msg}, args...)...) +} + +// Greaterf asserts that the first element is greater than the second +// +// assert.Greaterf(t, 2, 1, "error message %s", "formatted") +// assert.Greaterf(t, float64(2, "error message %s", "formatted"), float64(1)) +// assert.Greaterf(t, "b", "a", "error message %s", "formatted") +func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Greater(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// GreaterOrEqualf asserts that the first element is greater than or equal to the second +// +// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") +func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) +func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) +} + +// IsTypef asserts that the specified objects are of the same type. +func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") +func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Len(t, object, length, append([]interface{}{msg}, args...)...) +} + +// Lessf asserts that the first element is less than the second +// +// assert.Lessf(t, 1, 2, "error message %s", "formatted") +// assert.Lessf(t, float64(1, "error message %s", "formatted"), float64(2)) +// assert.Lessf(t, "a", "b", "error message %s", "formatted") +func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Less(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// LessOrEqualf asserts that the first element is less than or equal to the second +// +// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") +// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") +func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// Nilf asserts that the specified object is nil. +// +// assert.Nilf(t, err, "error message %s", "formatted") +func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Nil(t, object, append([]interface{}{msg}, args...)...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoErrorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NoError(t, err, append([]interface{}{msg}, args...)...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") +func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotEmpty(t, object, append([]interface{}{msg}, args...)...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// NotNilf asserts that the specified object is not nil. +// +// assert.NotNilf(t, err, "error message %s", "formatted") +func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotNil(t, object, append([]interface{}{msg}, args...)...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") +func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotPanics(t, f, append([]interface{}{msg}, args...)...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") +func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) +} + +// NotZerof asserts that i is not the zero value for its type. +func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotZero(t, i, append([]interface{}{msg}, args...)...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") +func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Panics(t, f, append([]interface{}{msg}, args...)...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") +func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) +} + +// Samef asserts that two pointers reference the same object. +// +// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Same(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Subset(t, list, subset, append([]interface{}{msg}, args...)...) +} + +// Truef asserts that the specified value is true. +// +// assert.Truef(t, myBool, "error message %s", "formatted") +func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return True(t, value, append([]interface{}{msg}, args...)...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// Zerof asserts that i is the zero value for its type. +func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Zero(t, i, append([]interface{}{msg}, args...)...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go new file mode 100644 index 000000000..26830403a --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -0,0 +1,1120 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Condition(a.t, comp, msgAndArgs...) +} + +// Conditionf uses a Comparison to assert a complex condition. +func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Conditionf(a.t, comp, msg, args...) +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Contains("Hello World", "World") +// a.Contains(["Hello", "World"], "World") +// a.Contains({"Hello": "World"}, "Hello") +func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Contains(a.t, s, contains, msgAndArgs...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Containsf("Hello World", "World", "error message %s", "formatted") +// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") +// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") +func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Containsf(a.t, s, contains, msg, args...) +} + +// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return DirExists(a.t, path, msgAndArgs...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return DirExistsf(a.t, path, msg, args...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) +func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ElementsMatch(a.t, listA, listB, msgAndArgs...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ElementsMatchf(a.t, listA, listB, msg, args...) +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Empty(obj) +func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Empty(a.t, object, msgAndArgs...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Emptyf(obj, "error message %s", "formatted") +func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Emptyf(a.t, object, msg, args...) +} + +// Equal asserts that two objects are equal. +// +// a.Equal(123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Equal(a.t, expected, actual, msgAndArgs...) +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString) +func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualError(a.t, theError, errString, msgAndArgs...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") +func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualErrorf(a.t, theError, errString, msg, args...) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValues(uint32(123), int32(123)) +func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualValues(a.t, expected, actual, msgAndArgs...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) +func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualValuesf(a.t, expected, actual, msg, args...) +} + +// Equalf asserts that two objects are equal. +// +// a.Equalf(123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Equalf(a.t, expected, actual, msg, args...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Error(err) { +// assert.Equal(t, expectedError, err) +// } +func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Error(a.t, err, msgAndArgs...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Errorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Errorf(a.t, err, msg, args...) +} + +// Eventually asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) +func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) +} + +// Eventuallyf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Eventuallyf(a.t, condition, waitFor, tick, msg, args...) +} + +// Exactly asserts that two objects are equal in value and type. +// +// a.Exactly(int32(123), int64(123)) +func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Exactly(a.t, expected, actual, msgAndArgs...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) +func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Exactlyf(a.t, expected, actual, msg, args...) +} + +// Fail reports a failure through +func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Fail(a.t, failureMessage, msgAndArgs...) +} + +// FailNow fails test +func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FailNow(a.t, failureMessage, msgAndArgs...) +} + +// FailNowf fails test +func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FailNowf(a.t, failureMessage, msg, args...) +} + +// Failf reports a failure through +func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Failf(a.t, failureMessage, msg, args...) +} + +// False asserts that the specified value is false. +// +// a.False(myBool) +func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return False(a.t, value, msgAndArgs...) +} + +// Falsef asserts that the specified value is false. +// +// a.Falsef(myBool, "error message %s", "formatted") +func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Falsef(a.t, value, msg, args...) +} + +// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FileExists(a.t, path, msgAndArgs...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FileExistsf(a.t, path, msg, args...) +} + +// Greater asserts that the first element is greater than the second +// +// a.Greater(2, 1) +// a.Greater(float64(2), float64(1)) +// a.Greater("b", "a") +func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Greater(a.t, e1, e2, msgAndArgs...) +} + +// GreaterOrEqual asserts that the first element is greater than or equal to the second +// +// a.GreaterOrEqual(2, 1) +// a.GreaterOrEqual(2, 2) +// a.GreaterOrEqual("b", "a") +// a.GreaterOrEqual("b", "b") +func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqual(a.t, e1, e2, msgAndArgs...) +} + +// GreaterOrEqualf asserts that the first element is greater than or equal to the second +// +// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") +// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") +// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") +// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") +func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqualf(a.t, e1, e2, msg, args...) +} + +// Greaterf asserts that the first element is greater than the second +// +// a.Greaterf(2, 1, "error message %s", "formatted") +// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1)) +// a.Greaterf("b", "a", "error message %s", "formatted") +func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Greaterf(a.t, e1, e2, msg, args...) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPError(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPErrorf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) +} + +// Implements asserts that an object is implemented by the specified interface. +// +// a.Implements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Implements(a.t, interfaceObject, object, msgAndArgs...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Implementsf(a.t, interfaceObject, object, msg, args...) +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// a.InDelta(math.Pi, (22 / 7.0), 0.01) +func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDelta(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) +func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaf(a.t, expected, actual, delta, msg, args...) +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) +} + +// IsType asserts that the specified objects are of the same type. +func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsType(a.t, expectedType, object, msgAndArgs...) +} + +// IsTypef asserts that the specified objects are of the same type. +func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsTypef(a.t, expectedType, object, msg, args...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return JSONEq(a.t, expected, actual, msgAndArgs...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return JSONEqf(a.t, expected, actual, msg, args...) +} + +// YAMLEq asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return YAMLEq(a.t, expected, actual, msgAndArgs...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return YAMLEqf(a.t, expected, actual, msg, args...) +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// a.Len(mySlice, 3) +func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Len(a.t, object, length, msgAndArgs...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// a.Lenf(mySlice, 3, "error message %s", "formatted") +func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Lenf(a.t, object, length, msg, args...) +} + +// Less asserts that the first element is less than the second +// +// a.Less(1, 2) +// a.Less(float64(1), float64(2)) +// a.Less("a", "b") +func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Less(a.t, e1, e2, msgAndArgs...) +} + +// LessOrEqual asserts that the first element is less than or equal to the second +// +// a.LessOrEqual(1, 2) +// a.LessOrEqual(2, 2) +// a.LessOrEqual("a", "b") +// a.LessOrEqual("b", "b") +func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return LessOrEqual(a.t, e1, e2, msgAndArgs...) +} + +// LessOrEqualf asserts that the first element is less than or equal to the second +// +// a.LessOrEqualf(1, 2, "error message %s", "formatted") +// a.LessOrEqualf(2, 2, "error message %s", "formatted") +// a.LessOrEqualf("a", "b", "error message %s", "formatted") +// a.LessOrEqualf("b", "b", "error message %s", "formatted") +func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return LessOrEqualf(a.t, e1, e2, msg, args...) +} + +// Lessf asserts that the first element is less than the second +// +// a.Lessf(1, 2, "error message %s", "formatted") +// a.Lessf(float64(1, "error message %s", "formatted"), float64(2)) +// a.Lessf("a", "b", "error message %s", "formatted") +func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Lessf(a.t, e1, e2, msg, args...) +} + +// Nil asserts that the specified object is nil. +// +// a.Nil(err) +func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Nil(a.t, object, msgAndArgs...) +} + +// Nilf asserts that the specified object is nil. +// +// a.Nilf(err, "error message %s", "formatted") +func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Nilf(a.t, object, msg, args...) +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoError(a.t, err, msgAndArgs...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoErrorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoErrorf(a.t, err, msg, args...) +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContains("Hello World", "Earth") +// a.NotContains(["Hello", "World"], "Earth") +// a.NotContains({"Hello": "World"}, "Earth") +func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotContains(a.t, s, contains, msgAndArgs...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") +// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") +// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") +func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotContainsf(a.t, s, contains, msg, args...) +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEmpty(a.t, object, msgAndArgs...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmptyf(obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEmptyf(a.t, object, msg, args...) +} + +// NotEqual asserts that the specified values are NOT equal. +// +// a.NotEqual(obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEqual(a.t, expected, actual, msgAndArgs...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// a.NotEqualf(obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEqualf(a.t, expected, actual, msg, args...) +} + +// NotNil asserts that the specified object is not nil. +// +// a.NotNil(err) +func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotNil(a.t, object, msgAndArgs...) +} + +// NotNilf asserts that the specified object is not nil. +// +// a.NotNilf(err, "error message %s", "formatted") +func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotNilf(a.t, object, msg, args...) +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanics(func(){ RemainCalm() }) +func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotPanics(a.t, f, msgAndArgs...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") +func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotPanicsf(a.t, f, msg, args...) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") +func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotRegexp(a.t, rx, str, msgAndArgs...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") +func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotRegexpf(a.t, rx, str, msg, args...) +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSubset(a.t, list, subset, msgAndArgs...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSubsetf(a.t, list, subset, msg, args...) +} + +// NotZero asserts that i is not the zero value for its type. +func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotZero(a.t, i, msgAndArgs...) +} + +// NotZerof asserts that i is not the zero value for its type. +func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotZerof(a.t, i, msg, args...) +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panics(func(){ GoCrazy() }) +func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Panics(a.t, f, msgAndArgs...) +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) +func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithValue(a.t, expected, f, msgAndArgs...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithValuef(a.t, expected, f, msg, args...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Panicsf(a.t, f, msg, args...) +} + +// Regexp asserts that a specified regexp matches a string. +// +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") +func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Regexp(a.t, rx, str, msgAndArgs...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") +func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Regexpf(a.t, rx, str, msg, args...) +} + +// Same asserts that two pointers reference the same object. +// +// a.Same(ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Same(a.t, expected, actual, msgAndArgs...) +} + +// Samef asserts that two pointers reference the same object. +// +// a.Samef(ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Samef(a.t, expected, actual, msg, args...) +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Subset(a.t, list, subset, msgAndArgs...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Subsetf(a.t, list, subset, msg, args...) +} + +// True asserts that the specified value is true. +// +// a.True(myBool) +func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return True(a.t, value, msgAndArgs...) +} + +// Truef asserts that the specified value is true. +// +// a.Truef(myBool, "error message %s", "formatted") +func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Truef(a.t, value, msg, args...) +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) +func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return WithinDurationf(a.t, expected, actual, delta, msg, args...) +} + +// Zero asserts that i is the zero value for its type. +func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Zero(a.t, i, msgAndArgs...) +} + +// Zerof asserts that i is the zero value for its type. +func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Zerof(a.t, i, msg, args...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go new file mode 100644 index 000000000..15a486ca6 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go @@ -0,0 +1,309 @@ +package assert + +import ( + "fmt" + "reflect" +) + +func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) { + switch kind { + case reflect.Int: + { + intobj1 := obj1.(int) + intobj2 := obj2.(int) + if intobj1 > intobj2 { + return -1, true + } + if intobj1 == intobj2 { + return 0, true + } + if intobj1 < intobj2 { + return 1, true + } + } + case reflect.Int8: + { + int8obj1 := obj1.(int8) + int8obj2 := obj2.(int8) + if int8obj1 > int8obj2 { + return -1, true + } + if int8obj1 == int8obj2 { + return 0, true + } + if int8obj1 < int8obj2 { + return 1, true + } + } + case reflect.Int16: + { + int16obj1 := obj1.(int16) + int16obj2 := obj2.(int16) + if int16obj1 > int16obj2 { + return -1, true + } + if int16obj1 == int16obj2 { + return 0, true + } + if int16obj1 < int16obj2 { + return 1, true + } + } + case reflect.Int32: + { + int32obj1 := obj1.(int32) + int32obj2 := obj2.(int32) + if int32obj1 > int32obj2 { + return -1, true + } + if int32obj1 == int32obj2 { + return 0, true + } + if int32obj1 < int32obj2 { + return 1, true + } + } + case reflect.Int64: + { + int64obj1 := obj1.(int64) + int64obj2 := obj2.(int64) + if int64obj1 > int64obj2 { + return -1, true + } + if int64obj1 == int64obj2 { + return 0, true + } + if int64obj1 < int64obj2 { + return 1, true + } + } + case reflect.Uint: + { + uintobj1 := obj1.(uint) + uintobj2 := obj2.(uint) + if uintobj1 > uintobj2 { + return -1, true + } + if uintobj1 == uintobj2 { + return 0, true + } + if uintobj1 < uintobj2 { + return 1, true + } + } + case reflect.Uint8: + { + uint8obj1 := obj1.(uint8) + uint8obj2 := obj2.(uint8) + if uint8obj1 > uint8obj2 { + return -1, true + } + if uint8obj1 == uint8obj2 { + return 0, true + } + if uint8obj1 < uint8obj2 { + return 1, true + } + } + case reflect.Uint16: + { + uint16obj1 := obj1.(uint16) + uint16obj2 := obj2.(uint16) + if uint16obj1 > uint16obj2 { + return -1, true + } + if uint16obj1 == uint16obj2 { + return 0, true + } + if uint16obj1 < uint16obj2 { + return 1, true + } + } + case reflect.Uint32: + { + uint32obj1 := obj1.(uint32) + uint32obj2 := obj2.(uint32) + if uint32obj1 > uint32obj2 { + return -1, true + } + if uint32obj1 == uint32obj2 { + return 0, true + } + if uint32obj1 < uint32obj2 { + return 1, true + } + } + case reflect.Uint64: + { + uint64obj1 := obj1.(uint64) + uint64obj2 := obj2.(uint64) + if uint64obj1 > uint64obj2 { + return -1, true + } + if uint64obj1 == uint64obj2 { + return 0, true + } + if uint64obj1 < uint64obj2 { + return 1, true + } + } + case reflect.Float32: + { + float32obj1 := obj1.(float32) + float32obj2 := obj2.(float32) + if float32obj1 > float32obj2 { + return -1, true + } + if float32obj1 == float32obj2 { + return 0, true + } + if float32obj1 < float32obj2 { + return 1, true + } + } + case reflect.Float64: + { + float64obj1 := obj1.(float64) + float64obj2 := obj2.(float64) + if float64obj1 > float64obj2 { + return -1, true + } + if float64obj1 == float64obj2 { + return 0, true + } + if float64obj1 < float64obj2 { + return 1, true + } + } + case reflect.String: + { + stringobj1 := obj1.(string) + stringobj2 := obj2.(string) + if stringobj1 > stringobj2 { + return -1, true + } + if stringobj1 == stringobj2 { + return 0, true + } + if stringobj1 < stringobj2 { + return 1, true + } + } + } + + return 0, false +} + +// Greater asserts that the first element is greater than the second +// +// assert.Greater(t, 2, 1) +// assert.Greater(t, float64(2), float64(1)) +// assert.Greater(t, "b", "a") +func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != -1 { + return Fail(t, fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// GreaterOrEqual asserts that the first element is greater than or equal to the second +// +// assert.GreaterOrEqual(t, 2, 1) +// assert.GreaterOrEqual(t, 2, 2) +// assert.GreaterOrEqual(t, "b", "a") +// assert.GreaterOrEqual(t, "b", "b") +func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != -1 && res != 0 { + return Fail(t, fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// Less asserts that the first element is less than the second +// +// assert.Less(t, 1, 2) +// assert.Less(t, float64(1), float64(2)) +// assert.Less(t, "a", "b") +func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != 1 { + return Fail(t, fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// LessOrEqual asserts that the first element is less than or equal to the second +// +// assert.LessOrEqual(t, 1, 2) +// assert.LessOrEqual(t, 2, 2) +// assert.LessOrEqual(t, "a", "b") +// assert.LessOrEqual(t, "b", "b") +func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != 1 && res != 0 { + return Fail(t, fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go new file mode 100644 index 000000000..044da8b01 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -0,0 +1,1498 @@ +package assert + +import ( + "bufio" + "bytes" + "encoding/json" + "errors" + "fmt" + "math" + "os" + "reflect" + "regexp" + "runtime" + "strings" + "time" + "unicode" + "unicode/utf8" + + "github.com/davecgh/go-spew/spew" + "github.com/pmezard/go-difflib/difflib" + yaml "gopkg.in/yaml.v2" +) + +//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Errorf(format string, args ...interface{}) +} + +// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful +// for table driven tests. +type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool + +// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful +// for table driven tests. +type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool + +// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful +// for table driven tests. +type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool + +// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful +// for table driven tests. +type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool + +// Comparison a custom function that returns true on success and false on failure +type Comparison func() (success bool) + +/* + Helper functions +*/ + +// ObjectsAreEqual determines if two objects are considered equal. +// +// This function does no assertion of any kind. +func ObjectsAreEqual(expected, actual interface{}) bool { + if expected == nil || actual == nil { + return expected == actual + } + + exp, ok := expected.([]byte) + if !ok { + return reflect.DeepEqual(expected, actual) + } + + act, ok := actual.([]byte) + if !ok { + return false + } + if exp == nil || act == nil { + return exp == nil && act == nil + } + return bytes.Equal(exp, act) +} + +// ObjectsAreEqualValues gets whether two objects are equal, or if their +// values are equal. +func ObjectsAreEqualValues(expected, actual interface{}) bool { + if ObjectsAreEqual(expected, actual) { + return true + } + + actualType := reflect.TypeOf(actual) + if actualType == nil { + return false + } + expectedValue := reflect.ValueOf(expected) + if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + // Attempt comparison after type conversion + return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + } + + return false +} + +/* CallerInfo is necessary because the assert functions use the testing object +internally, causing it to print the file:line of the assert method, rather than where +the problem actually occurred in calling code.*/ + +// CallerInfo returns an array of strings containing the file and line number +// of each stack frame leading from the current test to the assert call that +// failed. +func CallerInfo() []string { + + pc := uintptr(0) + file := "" + line := 0 + ok := false + name := "" + + callers := []string{} + for i := 0; ; i++ { + pc, file, line, ok = runtime.Caller(i) + if !ok { + // The breaks below failed to terminate the loop, and we ran off the + // end of the call stack. + break + } + + // This is a huge edge case, but it will panic if this is the case, see #180 + if file == "" { + break + } + + f := runtime.FuncForPC(pc) + if f == nil { + break + } + name = f.Name() + + // testing.tRunner is the standard library function that calls + // tests. Subtests are called directly by tRunner, without going through + // the Test/Benchmark/Example function that contains the t.Run calls, so + // with subtests we should break when we hit tRunner, without adding it + // to the list of callers. + if name == "testing.tRunner" { + break + } + + parts := strings.Split(file, "/") + file = parts[len(parts)-1] + if len(parts) > 1 { + dir := parts[len(parts)-2] + if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { + callers = append(callers, fmt.Sprintf("%s:%d", file, line)) + } + } + + // Drop the package + segments := strings.Split(name, ".") + name = segments[len(segments)-1] + if isTest(name, "Test") || + isTest(name, "Benchmark") || + isTest(name, "Example") { + break + } + } + + return callers +} + +// Stolen from the `go test` tool. +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) +} + +func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { + if len(msgAndArgs) == 0 || msgAndArgs == nil { + return "" + } + if len(msgAndArgs) == 1 { + msg := msgAndArgs[0] + if msgAsStr, ok := msg.(string); ok { + return msgAsStr + } + return fmt.Sprintf("%+v", msg) + } + if len(msgAndArgs) > 1 { + return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) + } + return "" +} + +// Aligns the provided message so that all lines after the first line start at the same location as the first line. +// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). +// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// basis on which the alignment occurs). +func indentMessageLines(message string, longestLabelLen int) string { + outBuf := new(bytes.Buffer) + + for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { + // no need to align first line because it starts at the correct location (after the label) + if i != 0 { + // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab + outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") + } + outBuf.WriteString(scanner.Text()) + } + + return outBuf.String() +} + +type failNower interface { + FailNow() +} + +// FailNow fails test +func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + Fail(t, failureMessage, msgAndArgs...) + + // We cannot extend TestingT with FailNow() and + // maintain backwards compatibility, so we fallback + // to panicking when FailNow is not available in + // TestingT. + // See issue #263 + + if t, ok := t.(failNower); ok { + t.FailNow() + } else { + panic("test failed and t is missing `FailNow()`") + } + return false +} + +// Fail reports a failure through +func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + content := []labeledContent{ + {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, + {"Error", failureMessage}, + } + + // Add test name if the Go version supports it + if n, ok := t.(interface { + Name() string + }); ok { + content = append(content, labeledContent{"Test", n.Name()}) + } + + message := messageFromMsgAndArgs(msgAndArgs...) + if len(message) > 0 { + content = append(content, labeledContent{"Messages", message}) + } + + t.Errorf("\n%s", ""+labeledOutput(content...)) + + return false +} + +type labeledContent struct { + label string + content string +} + +// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: +// +// \t{{label}}:{{align_spaces}}\t{{content}}\n +// +// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. +// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this +// alignment is achieved, "\t{{content}}\n" is added for the output. +// +// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. +func labeledOutput(content ...labeledContent) string { + longestLabel := 0 + for _, v := range content { + if len(v.label) > longestLabel { + longestLabel = len(v.label) + } + } + var output string + for _, v := range content { + output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" + } + return output +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) +func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) + } + if !reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) + } + + return true +} + +// IsType asserts that the specified objects are of the same type. +func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { + return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) + } + + return true +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(t, 123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err := validateEqualArgs(expected, actual); err != nil { + return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", + expected, actual, err), msgAndArgs...) + } + + if !ObjectsAreEqual(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// Same asserts that two pointers reference the same object. +// +// assert.Same(t, ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + expectedPtr, actualPtr := reflect.ValueOf(expected), reflect.ValueOf(actual) + if expectedPtr.Kind() != reflect.Ptr || actualPtr.Kind() != reflect.Ptr { + return Fail(t, "Invalid operation: both arguments must be pointers", msgAndArgs...) + } + + expectedType, actualType := reflect.TypeOf(expected), reflect.TypeOf(actual) + if expectedType != actualType { + return Fail(t, fmt.Sprintf("Pointer expected to be of type %v, but was %v", + expectedType, actualType), msgAndArgs...) + } + + if expected != actual { + return Fail(t, fmt.Sprintf("Not same: \n"+ + "expected: %p %#v\n"+ + "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) + } + + return true +} + +// formatUnequalValues takes two values of arbitrary types and returns string +// representations appropriate to be presented to the user. +// +// If the values are not of like type, the returned strings will be prefixed +// with the type name, and the value will be enclosed in parenthesis similar +// to a type conversion in the Go grammar. +func formatUnequalValues(expected, actual interface{}) (e string, a string) { + if reflect.TypeOf(expected) != reflect.TypeOf(actual) { + return fmt.Sprintf("%T(%#v)", expected, expected), + fmt.Sprintf("%T(%#v)", actual, actual) + } + + return fmt.Sprintf("%#v", expected), + fmt.Sprintf("%#v", actual) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(t, uint32(123), int32(123)) +func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if !ObjectsAreEqualValues(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// Exactly asserts that two objects are equal in value and type. +// +// assert.Exactly(t, int32(123), int64(123)) +func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + aType := reflect.TypeOf(expected) + bType := reflect.TypeOf(actual) + + if aType != bType { + return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) + } + + return Equal(t, expected, actual, msgAndArgs...) + +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(t, err) +func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !isNil(object) { + return true + } + return Fail(t, "Expected value not to be nil.", msgAndArgs...) +} + +// containsKind checks if a specified kind in the slice of kinds. +func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { + for i := 0; i < len(kinds); i++ { + if kind == kinds[i] { + return true + } + } + + return false +} + +// isNil checks if a specified object is nil or not, without Failing. +func isNil(object interface{}) bool { + if object == nil { + return true + } + + value := reflect.ValueOf(object) + kind := value.Kind() + isNilableKind := containsKind( + []reflect.Kind{ + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice}, + kind) + + if isNilableKind && value.IsNil() { + return true + } + + return false +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(t, err) +func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if isNil(object) { + return true + } + return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) +} + +// isEmpty gets whether the specified object is considered empty or not. +func isEmpty(object interface{}) bool { + + // get nil case out of the way + if object == nil { + return true + } + + objValue := reflect.ValueOf(object) + + switch objValue.Kind() { + // collection types are empty when they have no element + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + return objValue.Len() == 0 + // pointers are empty if nil or if the value they point to is empty + case reflect.Ptr: + if objValue.IsNil() { + return true + } + deref := objValue.Elem().Interface() + return isEmpty(deref) + // for all other types, compare against the zero value + default: + zero := reflect.Zero(objValue.Type()) + return reflect.DeepEqual(object, zero.Interface()) + } +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Empty(t, obj) +func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + pass := isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + pass := !isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// getLen try to get length of object. +// return (false, 0) if impossible. +func getLen(x interface{}) (ok bool, length int) { + v := reflect.ValueOf(x) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + return true, v.Len() +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(t, mySlice, 3) +func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + ok, l := getLen(object) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + } + + if l != length { + return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + } + return true +} + +// True asserts that the specified value is true. +// +// assert.True(t, myBool) +func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if h, ok := t.(interface { + Helper() + }); ok { + h.Helper() + } + + if value != true { + return Fail(t, "Should be true", msgAndArgs...) + } + + return true + +} + +// False asserts that the specified value is false. +// +// assert.False(t, myBool) +func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if value != false { + return Fail(t, "Should be false", msgAndArgs...) + } + + return true + +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(t, obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err := validateEqualArgs(expected, actual); err != nil { + return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", + expected, actual, err), msgAndArgs...) + } + + if ObjectsAreEqual(expected, actual) { + return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) + } + + return true + +} + +// containsElement try loop over the list check if the list includes the element. +// return (false, false) if impossible. +// return (true, false) if element was not found. +// return (true, true) if element was found. +func includeElement(list interface{}, element interface{}) (ok, found bool) { + + listValue := reflect.ValueOf(list) + listKind := reflect.TypeOf(list).Kind() + defer func() { + if e := recover(); e != nil { + ok = false + found = false + } + }() + + if listKind == reflect.String { + elementValue := reflect.ValueOf(element) + return true, strings.Contains(listValue.String(), elementValue.String()) + } + + if listKind == reflect.Map { + mapKeys := listValue.MapKeys() + for i := 0; i < len(mapKeys); i++ { + if ObjectsAreEqual(mapKeys[i].Interface(), element) { + return true, true + } + } + return true, false + } + + for i := 0; i < listValue.Len(); i++ { + if ObjectsAreEqual(listValue.Index(i).Interface(), element) { + return true, true + } + } + return true, false + +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Contains(t, "Hello World", "World") +// assert.Contains(t, ["Hello", "World"], "World") +// assert.Contains(t, {"Hello": "World"}, "Hello") +func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContains(t, "Hello World", "Earth") +// assert.NotContains(t, ["Hello", "World"], "Earth") +// assert.NotContains(t, {"Hello": "World"}, "Earth") +func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if found { + return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if subset == nil { + return true // we consider nil to be equal to the nil set + } + + subsetValue := reflect.ValueOf(subset) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + + listKind := reflect.TypeOf(list).Kind() + subsetKind := reflect.TypeOf(subset).Kind() + + if listKind != reflect.Array && listKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + } + + if subsetKind != reflect.Array && subsetKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + } + + for i := 0; i < subsetValue.Len(); i++ { + element := subsetValue.Index(i).Interface() + ok, found := includeElement(list, element) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...) + } + } + + return true +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if subset == nil { + return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) + } + + subsetValue := reflect.ValueOf(subset) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + + listKind := reflect.TypeOf(list).Kind() + subsetKind := reflect.TypeOf(subset).Kind() + + if listKind != reflect.Array && listKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + } + + if subsetKind != reflect.Array && subsetKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + } + + for i := 0; i < subsetValue.Len(); i++ { + element := subsetValue.Index(i).Interface() + ok, found := includeElement(list, element) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + } + if !found { + return true + } + } + + return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) +func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if isEmpty(listA) && isEmpty(listB) { + return true + } + + aKind := reflect.TypeOf(listA).Kind() + bKind := reflect.TypeOf(listB).Kind() + + if aKind != reflect.Array && aKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...) + } + + if bKind != reflect.Array && bKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...) + } + + aValue := reflect.ValueOf(listA) + bValue := reflect.ValueOf(listB) + + aLen := aValue.Len() + bLen := bValue.Len() + + if aLen != bLen { + return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...) + } + + // Mark indexes in bValue that we already used + visited := make([]bool, bLen) + for i := 0; i < aLen; i++ { + element := aValue.Index(i).Interface() + found := false + for j := 0; j < bLen; j++ { + if visited[j] { + continue + } + if ObjectsAreEqual(bValue.Index(j).Interface(), element) { + visited[j] = true + found = true + break + } + } + if !found { + return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...) + } + } + + return true +} + +// Condition uses a Comparison to assert a complex condition. +func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + result := comp() + if !result { + Fail(t, "Condition failed!", msgAndArgs...) + } + return result +} + +// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics +// methods, and represents a simple func that takes no arguments, and returns nothing. +type PanicTestFunc func() + +// didPanic returns true if the function passed to it panics. Otherwise, it returns false. +func didPanic(f PanicTestFunc) (bool, interface{}) { + + didPanic := false + var message interface{} + func() { + + defer func() { + if message = recover(); message != nil { + didPanic = true + } + }() + + // call the target function + f() + + }() + + return didPanic, message + +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(t, func(){ GoCrazy() }) +func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) + } + + return true +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) +func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + funcDidPanic, panicValue := didPanic(f) + if !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) + } + if panicValue != expected { + return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...) + } + + return true +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(t, func(){ RemainCalm() }) +func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if funcDidPanic, panicValue := didPanic(f); funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...) + } + + return true +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) +func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + dt := expected.Sub(actual) + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +func toFloat(x interface{}) (float64, bool) { + var xf float64 + xok := true + + switch xn := x.(type) { + case uint8: + xf = float64(xn) + case uint16: + xf = float64(xn) + case uint32: + xf = float64(xn) + case uint64: + xf = float64(xn) + case int: + xf = float64(xn) + case int8: + xf = float64(xn) + case int16: + xf = float64(xn) + case int32: + xf = float64(xn) + case int64: + xf = float64(xn) + case float32: + xf = float64(xn) + case float64: + xf = float64(xn) + case time.Duration: + xf = float64(xn) + default: + xok = false + } + + return xf, xok +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) +func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + af, aok := toFloat(expected) + bf, bok := toFloat(actual) + + if !aok || !bok { + return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) + } + + if math.IsNaN(af) { + return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...) + } + + if math.IsNaN(bf) { + return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) + } + + dt := af - bf + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) + if !result { + return result + } + } + + return true +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Map || + reflect.TypeOf(expected).Kind() != reflect.Map { + return Fail(t, "Arguments must be maps", msgAndArgs...) + } + + expectedMap := reflect.ValueOf(expected) + actualMap := reflect.ValueOf(actual) + + if expectedMap.Len() != actualMap.Len() { + return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) + } + + for _, k := range expectedMap.MapKeys() { + ev := expectedMap.MapIndex(k) + av := actualMap.MapIndex(k) + + if !ev.IsValid() { + return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) + } + + if !av.IsValid() { + return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) + } + + if !InDelta( + t, + ev.Interface(), + av.Interface(), + delta, + msgAndArgs..., + ) { + return false + } + } + + return true +} + +func calcRelativeError(expected, actual interface{}) (float64, error) { + af, aok := toFloat(expected) + if !aok { + return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) + } + if af == 0 { + return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") + } + bf, bok := toFloat(actual) + if !bok { + return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) + } + + return math.Abs(af-bf) / math.Abs(af), nil +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + actualEpsilon, err := calcRelativeError(expected, actual) + if err != nil { + return Fail(t, err.Error(), msgAndArgs...) + } + if actualEpsilon > epsilon { + return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ + " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) + } + + return true +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) + if !result { + return result + } + } + + return true +} + +/* + Errors +*/ + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err != nil { + return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) + } + + return true +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err) { +// assert.Equal(t, expectedError, err) +// } +func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if err == nil { + return Fail(t, "An error is expected but got nil.", msgAndArgs...) + } + + return true +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString) +func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !Error(t, theError, msgAndArgs...) { + return false + } + expected := errString + actual := theError.Error() + // don't need to use deep equals here, we know they are both strings + if expected != actual { + return Fail(t, fmt.Sprintf("Error message not equal:\n"+ + "expected: %q\n"+ + "actual : %q", expected, actual), msgAndArgs...) + } + return true +} + +// matchRegexp return true if a specified regexp matches a string. +func matchRegexp(rx interface{}, str interface{}) bool { + + var r *regexp.Regexp + if rr, ok := rx.(*regexp.Regexp); ok { + r = rr + } else { + r = regexp.MustCompile(fmt.Sprint(rx)) + } + + return (r.FindStringIndex(fmt.Sprint(str)) != nil) + +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + match := matchRegexp(rx, str) + + if !match { + Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) + } + + return match +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + match := matchRegexp(rx, str) + + if match { + Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) + } + + return !match + +} + +// Zero asserts that i is the zero value for its type. +func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// NotZero asserts that i is not the zero value for its type. +func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) + } + return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) + } + if info.IsDir() { + return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) + } + return true +} + +// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) + } + return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) + } + if !info.IsDir() { + return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) + } + return true +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + var expectedJSONAsInterface, actualJSONAsInterface interface{} + + if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) +} + +// YAMLEq asserts that two YAML strings are equivalent. +func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + var expectedYAMLAsInterface, actualYAMLAsInterface interface{} + + if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) +} + +func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { + t := reflect.TypeOf(v) + k := t.Kind() + + if k == reflect.Ptr { + t = t.Elem() + k = t.Kind() + } + return t, k +} + +// diff returns a diff of both values as long as both are of the same type and +// are a struct, map, slice, array or string. Otherwise it returns an empty string. +func diff(expected interface{}, actual interface{}) string { + if expected == nil || actual == nil { + return "" + } + + et, ek := typeAndKind(expected) + at, _ := typeAndKind(actual) + + if et != at { + return "" + } + + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { + return "" + } + + var e, a string + if et != reflect.TypeOf("") { + e = spewConfig.Sdump(expected) + a = spewConfig.Sdump(actual) + } else { + e = reflect.ValueOf(expected).String() + a = reflect.ValueOf(actual).String() + } + + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(e), + B: difflib.SplitLines(a), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + + return "\n\nDiff:\n" + diff +} + +// validateEqualArgs checks whether provided arguments can be safely used in the +// Equal/NotEqual functions. +func validateEqualArgs(expected, actual interface{}) error { + if isFunction(expected) || isFunction(actual) { + return errors.New("cannot take func type as argument") + } + return nil +} + +func isFunction(arg interface{}) bool { + if arg == nil { + return false + } + return reflect.TypeOf(arg).Kind() == reflect.Func +} + +var spewConfig = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, +} + +type tHelper interface { + Helper() +} + +// Eventually asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) +func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + timer := time.NewTimer(waitFor) + ticker := time.NewTicker(tick) + checkPassed := make(chan bool) + defer timer.Stop() + defer ticker.Stop() + defer close(checkPassed) + for { + select { + case <-timer.C: + return Fail(t, "Condition never satisfied", msgAndArgs...) + case result := <-checkPassed: + if result { + return true + } + case <-ticker.C: + go func() { + checkPassed <- condition() + }() + } + } +} diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go new file mode 100644 index 000000000..c9dccc4d6 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/doc.go @@ -0,0 +1,45 @@ +// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. +// +// Example Usage +// +// The following is a complete example using assert in a standard test function: +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(t, a, b, "The two words should be the same.") +// +// } +// +// if you assert many times, use the format below: +// +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// assert := assert.New(t) +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(a, b, "The two words should be the same.") +// } +// +// Assertions +// +// Assertions allow you to easily write test code, and are global funcs in the `assert` package. +// All assertion functions take, as the first argument, the `*testing.T` object provided by the +// testing framework. This allows the assertion funcs to write the failings and other details to +// the correct place. +// +// Every assertion function also takes an optional string message as the final argument, +// allowing custom error messages to be appended to the message the assertion method outputs. +package assert diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go new file mode 100644 index 000000000..ac9dc9d1d --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/errors.go @@ -0,0 +1,10 @@ +package assert + +import ( + "errors" +) + +// AnError is an error instance useful for testing. If the code does not care +// about error specifics, and only needs to return the error for example, this +// error should be used to make the test code more readable. +var AnError = errors.New("assert.AnError general error for testing") diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go new file mode 100644 index 000000000..9ad56851d --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go @@ -0,0 +1,16 @@ +package assert + +// Assertions provides assertion methods around the +// TestingT interface. +type Assertions struct { + t TestingT +} + +// New makes a new Assertions object for the specified TestingT. +func New(t TestingT) *Assertions { + return &Assertions{ + t: t, + } +} + +//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go new file mode 100644 index 000000000..df46fa777 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -0,0 +1,143 @@ +package assert + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "strings" +) + +// httpCode is a helper that returns HTTP code of the response. It returns -1 and +// an error if building a new request fails. +func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url, nil) + if err != nil { + return -1, err + } + req.URL.RawQuery = values.Encode() + handler(w, req) + return w.Code, nil +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent + if !isSuccessCode { + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isSuccessCode +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect + if !isRedirectCode { + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isRedirectCode +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isErrorCode := code >= http.StatusBadRequest + if !isErrorCode { + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isErrorCode +} + +// HTTPBody is a helper that returns HTTP body of the response. It returns +// empty string if building a new request fails. +func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if err != nil { + return "" + } + handler(w, req) + return w.Body.String() +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if !contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return contains +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return !contains +} diff --git a/vendor/github.com/stretchr/testify/go.mod b/vendor/github.com/stretchr/testify/go.mod new file mode 100644 index 000000000..50536488c --- /dev/null +++ b/vendor/github.com/stretchr/testify/go.mod @@ -0,0 +1,8 @@ +module github.com/stretchr/testify + +require ( + github.com/davecgh/go-spew v1.1.0 + github.com/pmezard/go-difflib v1.0.0 + github.com/stretchr/objx v0.1.0 + gopkg.in/yaml.v2 v2.2.2 +) diff --git a/vendor/github.com/stretchr/testify/require/doc.go b/vendor/github.com/stretchr/testify/require/doc.go new file mode 100644 index 000000000..169de3922 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/doc.go @@ -0,0 +1,28 @@ +// Package require implements the same assertions as the `assert` package but +// stops test execution when a test fails. +// +// Example Usage +// +// The following is a complete example using require in a standard test function: +// import ( +// "testing" +// "github.com/stretchr/testify/require" +// ) +// +// func TestSomething(t *testing.T) { +// +// var a string = "Hello" +// var b string = "Hello" +// +// require.Equal(t, a, b, "The two words should be the same.") +// +// } +// +// Assertions +// +// The `require` package have same global functions as in the `assert` package, +// but instead of returning a boolean result they call `t.FailNow()`. +// +// Every assertion function also takes an optional string message as the final argument, +// allowing custom error messages to be appended to the message the assertion method outputs. +package require diff --git a/vendor/github.com/stretchr/testify/require/forward_requirements.go b/vendor/github.com/stretchr/testify/require/forward_requirements.go new file mode 100644 index 000000000..ac71d4058 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/forward_requirements.go @@ -0,0 +1,16 @@ +package require + +// Assertions provides assertion methods around the +// TestingT interface. +type Assertions struct { + t TestingT +} + +// New makes a new Assertions object for the specified TestingT. +func New(t TestingT) *Assertions { + return &Assertions{ + t: t, + } +} + +//go:generate go run ../_codegen/main.go -output-package=require -template=require_forward.go.tmpl -include-format-funcs diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go new file mode 100644 index 000000000..c5903f5db --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -0,0 +1,1433 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package require + +import ( + assert "github.com/stretchr/testify/assert" + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Condition(t, comp, msgAndArgs...) { + return + } + t.FailNow() +} + +// Conditionf uses a Comparison to assert a complex condition. +func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Conditionf(t, comp, msg, args...) { + return + } + t.FailNow() +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Contains(t, "Hello World", "World") +// assert.Contains(t, ["Hello", "World"], "World") +// assert.Contains(t, {"Hello": "World"}, "Hello") +func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Contains(t, s, contains, msgAndArgs...) { + return + } + t.FailNow() +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") +// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") +// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") +func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Containsf(t, s, contains, msg, args...) { + return + } + t.FailNow() +} + +// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.DirExists(t, path, msgAndArgs...) { + return + } + t.FailNow() +} + +// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.DirExistsf(t, path, msg, args...) { + return + } + t.FailNow() +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) +func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ElementsMatch(t, listA, listB, msgAndArgs...) { + return + } + t.FailNow() +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ElementsMatchf(t, listA, listB, msg, args...) { + return + } + t.FailNow() +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Empty(t, obj) +func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Empty(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Emptyf(t, obj, "error message %s", "formatted") +func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Emptyf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(t, 123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Equal(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString) +func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.EqualError(t, theError, errString, msgAndArgs...) { + return + } + t.FailNow() +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") +func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.EqualErrorf(t, theError, errString, msg, args...) { + return + } + t.FailNow() +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(t, uint32(123), int32(123)) +func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.EqualValues(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) +func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.EqualValuesf(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + +// Equalf asserts that two objects are equal. +// +// assert.Equalf(t, 123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Equalf(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err) { +// assert.Equal(t, expectedError, err) +// } +func Error(t TestingT, err error, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Error(t, err, msgAndArgs...) { + return + } + t.FailNow() +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Errorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func Errorf(t TestingT, err error, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Errorf(t, err, msg, args...) { + return + } + t.FailNow() +} + +// Eventually asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) +func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { + if assert.Eventually(t, condition, waitFor, tick, msgAndArgs...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + +// Eventuallyf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { + if assert.Eventuallyf(t, condition, waitFor, tick, msg, args...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + +// Exactly asserts that two objects are equal in value and type. +// +// assert.Exactly(t, int32(123), int64(123)) +func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Exactly(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) +func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Exactlyf(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + +// Fail reports a failure through +func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Fail(t, failureMessage, msgAndArgs...) { + return + } + t.FailNow() +} + +// FailNow fails test +func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.FailNow(t, failureMessage, msgAndArgs...) { + return + } + t.FailNow() +} + +// FailNowf fails test +func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.FailNowf(t, failureMessage, msg, args...) { + return + } + t.FailNow() +} + +// Failf reports a failure through +func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Failf(t, failureMessage, msg, args...) { + return + } + t.FailNow() +} + +// False asserts that the specified value is false. +// +// assert.False(t, myBool) +func False(t TestingT, value bool, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.False(t, value, msgAndArgs...) { + return + } + t.FailNow() +} + +// Falsef asserts that the specified value is false. +// +// assert.Falsef(t, myBool, "error message %s", "formatted") +func Falsef(t TestingT, value bool, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Falsef(t, value, msg, args...) { + return + } + t.FailNow() +} + +// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.FileExists(t, path, msgAndArgs...) { + return + } + t.FailNow() +} + +// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.FileExistsf(t, path, msg, args...) { + return + } + t.FailNow() +} + +// Greater asserts that the first element is greater than the second +// +// assert.Greater(t, 2, 1) +// assert.Greater(t, float64(2), float64(1)) +// assert.Greater(t, "b", "a") +func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Greater(t, e1, e2, msgAndArgs...) { + return + } + t.FailNow() +} + +// GreaterOrEqual asserts that the first element is greater than or equal to the second +// +// assert.GreaterOrEqual(t, 2, 1) +// assert.GreaterOrEqual(t, 2, 2) +// assert.GreaterOrEqual(t, "b", "a") +// assert.GreaterOrEqual(t, "b", "b") +func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.GreaterOrEqual(t, e1, e2, msgAndArgs...) { + return + } + t.FailNow() +} + +// GreaterOrEqualf asserts that the first element is greater than or equal to the second +// +// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") +func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.GreaterOrEqualf(t, e1, e2, msg, args...) { + return + } + t.FailNow() +} + +// Greaterf asserts that the first element is greater than the second +// +// assert.Greaterf(t, 2, 1, "error message %s", "formatted") +// assert.Greaterf(t, float64(2, "error message %s", "formatted"), float64(1)) +// assert.Greaterf(t, "b", "a", "error message %s", "formatted") +func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Greaterf(t, e1, e2, msg, args...) { + return + } + t.FailNow() +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { + return + } + t.FailNow() +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { + return + } + t.FailNow() +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { + return + } + t.FailNow() +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { + return + } + t.FailNow() +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { + return + } + t.FailNow() +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { + return + } + t.FailNow() +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { + return + } + t.FailNow() +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { + return + } + t.FailNow() +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { + return + } + t.FailNow() +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { + return + } + t.FailNow() +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) +func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Implements(t, interfaceObject, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Implementsf(t, interfaceObject, object, msg, args...) { + return + } + t.FailNow() +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) +func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InDelta(t, expected, actual, delta, msgAndArgs...) { + return + } + t.FailNow() +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { + return + } + t.FailNow() +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { + return + } + t.FailNow() +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { + return + } + t.FailNow() +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { + return + } + t.FailNow() +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) +func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InDeltaf(t, expected, actual, delta, msg, args...) { + return + } + t.FailNow() +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { + return + } + t.FailNow() +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { + return + } + t.FailNow() +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { + return + } + t.FailNow() +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { + return + } + t.FailNow() +} + +// IsType asserts that the specified objects are of the same type. +func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsType(t, expectedType, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsTypef asserts that the specified objects are of the same type. +func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsTypef(t, expectedType, object, msg, args...) { + return + } + t.FailNow() +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.JSONEq(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.JSONEqf(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + +// YAMLEq asserts that two YAML strings are equivalent. +func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.YAMLEq(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.YAMLEqf(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(t, mySlice, 3) +func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Len(t, object, length, msgAndArgs...) { + return + } + t.FailNow() +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") +func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Lenf(t, object, length, msg, args...) { + return + } + t.FailNow() +} + +// Less asserts that the first element is less than the second +// +// assert.Less(t, 1, 2) +// assert.Less(t, float64(1), float64(2)) +// assert.Less(t, "a", "b") +func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Less(t, e1, e2, msgAndArgs...) { + return + } + t.FailNow() +} + +// LessOrEqual asserts that the first element is less than or equal to the second +// +// assert.LessOrEqual(t, 1, 2) +// assert.LessOrEqual(t, 2, 2) +// assert.LessOrEqual(t, "a", "b") +// assert.LessOrEqual(t, "b", "b") +func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.LessOrEqual(t, e1, e2, msgAndArgs...) { + return + } + t.FailNow() +} + +// LessOrEqualf asserts that the first element is less than or equal to the second +// +// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") +// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") +func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.LessOrEqualf(t, e1, e2, msg, args...) { + return + } + t.FailNow() +} + +// Lessf asserts that the first element is less than the second +// +// assert.Lessf(t, 1, 2, "error message %s", "formatted") +// assert.Lessf(t, float64(1, "error message %s", "formatted"), float64(2)) +// assert.Lessf(t, "a", "b", "error message %s", "formatted") +func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Lessf(t, e1, e2, msg, args...) { + return + } + t.FailNow() +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(t, err) +func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Nil(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// Nilf asserts that the specified object is nil. +// +// assert.Nilf(t, err, "error message %s", "formatted") +func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Nilf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoError(t TestingT, err error, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NoError(t, err, msgAndArgs...) { + return + } + t.FailNow() +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoErrorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NoErrorf(t, err, msg, args...) { + return + } + t.FailNow() +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContains(t, "Hello World", "Earth") +// assert.NotContains(t, ["Hello", "World"], "Earth") +// assert.NotContains(t, {"Hello": "World"}, "Earth") +func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotContains(t, s, contains, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") +func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotContainsf(t, s, contains, msg, args...) { + return + } + t.FailNow() +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotEmpty(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotEmptyf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(t, obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotEqual(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotEqualf(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(t, err) +func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotNil(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotNilf asserts that the specified object is not nil. +// +// assert.NotNilf(t, err, "error message %s", "formatted") +func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotNilf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(t, func(){ RemainCalm() }) +func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotPanics(t, f, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") +func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotPanicsf(t, f, msg, args...) { + return + } + t.FailNow() +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotRegexp(t, rx, str, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") +func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotRegexpf(t, rx, str, msg, args...) { + return + } + t.FailNow() +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotSubset(t, list, subset, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotSubsetf(t, list, subset, msg, args...) { + return + } + t.FailNow() +} + +// NotZero asserts that i is not the zero value for its type. +func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotZero(t, i, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotZerof asserts that i is not the zero value for its type. +func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotZerof(t, i, msg, args...) { + return + } + t.FailNow() +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(t, func(){ GoCrazy() }) +func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Panics(t, f, msgAndArgs...) { + return + } + t.FailNow() +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) +func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.PanicsWithValue(t, expected, f, msgAndArgs...) { + return + } + t.FailNow() +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.PanicsWithValuef(t, expected, f, msg, args...) { + return + } + t.FailNow() +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") +func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Panicsf(t, f, msg, args...) { + return + } + t.FailNow() +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Regexp(t, rx, str, msgAndArgs...) { + return + } + t.FailNow() +} + +// Regexpf asserts that a specified regexp matches a string. +// +// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") +func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Regexpf(t, rx, str, msg, args...) { + return + } + t.FailNow() +} + +// Same asserts that two pointers reference the same object. +// +// assert.Same(t, ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func Same(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Same(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// Samef asserts that two pointers reference the same object. +// +// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Samef(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Subset(t, list, subset, msgAndArgs...) { + return + } + t.FailNow() +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Subsetf(t, list, subset, msg, args...) { + return + } + t.FailNow() +} + +// True asserts that the specified value is true. +// +// assert.True(t, myBool) +func True(t TestingT, value bool, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.True(t, value, msgAndArgs...) { + return + } + t.FailNow() +} + +// Truef asserts that the specified value is true. +// +// assert.Truef(t, myBool, "error message %s", "formatted") +func Truef(t TestingT, value bool, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Truef(t, value, msg, args...) { + return + } + t.FailNow() +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) +func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { + return + } + t.FailNow() +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.WithinDurationf(t, expected, actual, delta, msg, args...) { + return + } + t.FailNow() +} + +// Zero asserts that i is the zero value for its type. +func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Zero(t, i, msgAndArgs...) { + return + } + t.FailNow() +} + +// Zerof asserts that i is the zero value for its type. +func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Zerof(t, i, msg, args...) { + return + } + t.FailNow() +} diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go new file mode 100644 index 000000000..804fae035 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -0,0 +1,1121 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package require + +import ( + assert "github.com/stretchr/testify/assert" + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Condition(a.t, comp, msgAndArgs...) +} + +// Conditionf uses a Comparison to assert a complex condition. +func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Conditionf(a.t, comp, msg, args...) +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Contains("Hello World", "World") +// a.Contains(["Hello", "World"], "World") +// a.Contains({"Hello": "World"}, "Hello") +func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Contains(a.t, s, contains, msgAndArgs...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Containsf("Hello World", "World", "error message %s", "formatted") +// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") +// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") +func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Containsf(a.t, s, contains, msg, args...) +} + +// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + DirExists(a.t, path, msgAndArgs...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + DirExistsf(a.t, path, msg, args...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) +func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ElementsMatch(a.t, listA, listB, msgAndArgs...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ElementsMatchf(a.t, listA, listB, msg, args...) +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Empty(obj) +func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Empty(a.t, object, msgAndArgs...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Emptyf(obj, "error message %s", "formatted") +func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Emptyf(a.t, object, msg, args...) +} + +// Equal asserts that two objects are equal. +// +// a.Equal(123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Equal(a.t, expected, actual, msgAndArgs...) +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString) +func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + EqualError(a.t, theError, errString, msgAndArgs...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") +func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + EqualErrorf(a.t, theError, errString, msg, args...) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValues(uint32(123), int32(123)) +func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + EqualValues(a.t, expected, actual, msgAndArgs...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) +func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + EqualValuesf(a.t, expected, actual, msg, args...) +} + +// Equalf asserts that two objects are equal. +// +// a.Equalf(123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Equalf(a.t, expected, actual, msg, args...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Error(err) { +// assert.Equal(t, expectedError, err) +// } +func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Error(a.t, err, msgAndArgs...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Errorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Errorf(a.t, err, msg, args...) +} + +// Eventually asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) +func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Eventually(a.t, condition, waitFor, tick, msgAndArgs...) +} + +// Eventuallyf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Eventuallyf(a.t, condition, waitFor, tick, msg, args...) +} + +// Exactly asserts that two objects are equal in value and type. +// +// a.Exactly(int32(123), int64(123)) +func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Exactly(a.t, expected, actual, msgAndArgs...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) +func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Exactlyf(a.t, expected, actual, msg, args...) +} + +// Fail reports a failure through +func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Fail(a.t, failureMessage, msgAndArgs...) +} + +// FailNow fails test +func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + FailNow(a.t, failureMessage, msgAndArgs...) +} + +// FailNowf fails test +func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + FailNowf(a.t, failureMessage, msg, args...) +} + +// Failf reports a failure through +func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Failf(a.t, failureMessage, msg, args...) +} + +// False asserts that the specified value is false. +// +// a.False(myBool) +func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + False(a.t, value, msgAndArgs...) +} + +// Falsef asserts that the specified value is false. +// +// a.Falsef(myBool, "error message %s", "formatted") +func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Falsef(a.t, value, msg, args...) +} + +// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + FileExists(a.t, path, msgAndArgs...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + FileExistsf(a.t, path, msg, args...) +} + +// Greater asserts that the first element is greater than the second +// +// a.Greater(2, 1) +// a.Greater(float64(2), float64(1)) +// a.Greater("b", "a") +func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Greater(a.t, e1, e2, msgAndArgs...) +} + +// GreaterOrEqual asserts that the first element is greater than or equal to the second +// +// a.GreaterOrEqual(2, 1) +// a.GreaterOrEqual(2, 2) +// a.GreaterOrEqual("b", "a") +// a.GreaterOrEqual("b", "b") +func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + GreaterOrEqual(a.t, e1, e2, msgAndArgs...) +} + +// GreaterOrEqualf asserts that the first element is greater than or equal to the second +// +// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") +// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") +// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") +// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") +func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + GreaterOrEqualf(a.t, e1, e2, msg, args...) +} + +// Greaterf asserts that the first element is greater than the second +// +// a.Greaterf(2, 1, "error message %s", "formatted") +// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1)) +// a.Greaterf("b", "a", "error message %s", "formatted") +func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Greaterf(a.t, e1, e2, msg, args...) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPError(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPErrorf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPRedirectf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HTTPSuccessf(a.t, handler, method, url, values, msg, args...) +} + +// Implements asserts that an object is implemented by the specified interface. +// +// a.Implements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Implements(a.t, interfaceObject, object, msgAndArgs...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Implementsf(a.t, interfaceObject, object, msg, args...) +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// a.InDelta(math.Pi, (22 / 7.0), 0.01) +func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InDelta(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InDeltaSlicef(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) +func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InDeltaf(a.t, expected, actual, delta, msg, args...) +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + InEpsilonf(a.t, expected, actual, epsilon, msg, args...) +} + +// IsType asserts that the specified objects are of the same type. +func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsType(a.t, expectedType, object, msgAndArgs...) +} + +// IsTypef asserts that the specified objects are of the same type. +func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsTypef(a.t, expectedType, object, msg, args...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + JSONEq(a.t, expected, actual, msgAndArgs...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + JSONEqf(a.t, expected, actual, msg, args...) +} + +// YAMLEq asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + YAMLEq(a.t, expected, actual, msgAndArgs...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + YAMLEqf(a.t, expected, actual, msg, args...) +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// a.Len(mySlice, 3) +func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Len(a.t, object, length, msgAndArgs...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// a.Lenf(mySlice, 3, "error message %s", "formatted") +func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Lenf(a.t, object, length, msg, args...) +} + +// Less asserts that the first element is less than the second +// +// a.Less(1, 2) +// a.Less(float64(1), float64(2)) +// a.Less("a", "b") +func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Less(a.t, e1, e2, msgAndArgs...) +} + +// LessOrEqual asserts that the first element is less than or equal to the second +// +// a.LessOrEqual(1, 2) +// a.LessOrEqual(2, 2) +// a.LessOrEqual("a", "b") +// a.LessOrEqual("b", "b") +func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + LessOrEqual(a.t, e1, e2, msgAndArgs...) +} + +// LessOrEqualf asserts that the first element is less than or equal to the second +// +// a.LessOrEqualf(1, 2, "error message %s", "formatted") +// a.LessOrEqualf(2, 2, "error message %s", "formatted") +// a.LessOrEqualf("a", "b", "error message %s", "formatted") +// a.LessOrEqualf("b", "b", "error message %s", "formatted") +func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + LessOrEqualf(a.t, e1, e2, msg, args...) +} + +// Lessf asserts that the first element is less than the second +// +// a.Lessf(1, 2, "error message %s", "formatted") +// a.Lessf(float64(1, "error message %s", "formatted"), float64(2)) +// a.Lessf("a", "b", "error message %s", "formatted") +func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Lessf(a.t, e1, e2, msg, args...) +} + +// Nil asserts that the specified object is nil. +// +// a.Nil(err) +func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Nil(a.t, object, msgAndArgs...) +} + +// Nilf asserts that the specified object is nil. +// +// a.Nilf(err, "error message %s", "formatted") +func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Nilf(a.t, object, msg, args...) +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NoError(a.t, err, msgAndArgs...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoErrorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NoErrorf(a.t, err, msg, args...) +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContains("Hello World", "Earth") +// a.NotContains(["Hello", "World"], "Earth") +// a.NotContains({"Hello": "World"}, "Earth") +func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotContains(a.t, s, contains, msgAndArgs...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") +// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") +// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") +func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotContainsf(a.t, s, contains, msg, args...) +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotEmpty(a.t, object, msgAndArgs...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmptyf(obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotEmptyf(a.t, object, msg, args...) +} + +// NotEqual asserts that the specified values are NOT equal. +// +// a.NotEqual(obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotEqual(a.t, expected, actual, msgAndArgs...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// a.NotEqualf(obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotEqualf(a.t, expected, actual, msg, args...) +} + +// NotNil asserts that the specified object is not nil. +// +// a.NotNil(err) +func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotNil(a.t, object, msgAndArgs...) +} + +// NotNilf asserts that the specified object is not nil. +// +// a.NotNilf(err, "error message %s", "formatted") +func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotNilf(a.t, object, msg, args...) +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanics(func(){ RemainCalm() }) +func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotPanics(a.t, f, msgAndArgs...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") +func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotPanicsf(a.t, f, msg, args...) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") +func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotRegexp(a.t, rx, str, msgAndArgs...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") +func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotRegexpf(a.t, rx, str, msg, args...) +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotSubset(a.t, list, subset, msgAndArgs...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotSubsetf(a.t, list, subset, msg, args...) +} + +// NotZero asserts that i is not the zero value for its type. +func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotZero(a.t, i, msgAndArgs...) +} + +// NotZerof asserts that i is not the zero value for its type. +func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotZerof(a.t, i, msg, args...) +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panics(func(){ GoCrazy() }) +func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Panics(a.t, f, msgAndArgs...) +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) +func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + PanicsWithValue(a.t, expected, f, msgAndArgs...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + PanicsWithValuef(a.t, expected, f, msg, args...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Panicsf(a.t, f, msg, args...) +} + +// Regexp asserts that a specified regexp matches a string. +// +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") +func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Regexp(a.t, rx, str, msgAndArgs...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") +func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Regexpf(a.t, rx, str, msg, args...) +} + +// Same asserts that two pointers reference the same object. +// +// a.Same(ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Same(a.t, expected, actual, msgAndArgs...) +} + +// Samef asserts that two pointers reference the same object. +// +// a.Samef(ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Samef(a.t, expected, actual, msg, args...) +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Subset(a.t, list, subset, msgAndArgs...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Subsetf(a.t, list, subset, msg, args...) +} + +// True asserts that the specified value is true. +// +// a.True(myBool) +func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + True(a.t, value, msgAndArgs...) +} + +// Truef asserts that the specified value is true. +// +// a.Truef(myBool, "error message %s", "formatted") +func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Truef(a.t, value, msg, args...) +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) +func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + WithinDuration(a.t, expected, actual, delta, msgAndArgs...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + WithinDurationf(a.t, expected, actual, delta, msg, args...) +} + +// Zero asserts that i is the zero value for its type. +func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Zero(a.t, i, msgAndArgs...) +} + +// Zerof asserts that i is the zero value for its type. +func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Zerof(a.t, i, msg, args...) +} diff --git a/vendor/github.com/stretchr/testify/require/requirements.go b/vendor/github.com/stretchr/testify/require/requirements.go new file mode 100644 index 000000000..6b85c5ece --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/requirements.go @@ -0,0 +1,29 @@ +package require + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Errorf(format string, args ...interface{}) + FailNow() +} + +type tHelper interface { + Helper() +} + +// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful +// for table driven tests. +type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) + +// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful +// for table driven tests. +type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) + +// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful +// for table driven tests. +type BoolAssertionFunc func(TestingT, bool, ...interface{}) + +// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful +// for table driven tests. +type ErrorAssertionFunc func(TestingT, error, ...interface{}) + +//go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs diff --git a/vendor/github.com/containerd/cri/LICENSE b/vendor/k8s.io/component-base/LICENSE similarity index 99% rename from vendor/github.com/containerd/cri/LICENSE rename to vendor/k8s.io/component-base/LICENSE index 8dada3eda..d64569567 100644 --- a/vendor/github.com/containerd/cri/LICENSE +++ b/vendor/k8s.io/component-base/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -178,7 +179,7 @@ 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 "{}" + 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 @@ -186,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/k8s.io/component-base/README.md b/vendor/k8s.io/component-base/README.md new file mode 100644 index 000000000..0b6d35c64 --- /dev/null +++ b/vendor/k8s.io/component-base/README.md @@ -0,0 +1,34 @@ +## component-base + +## Purpose + +Implement KEP 32: https://github.com/kubernetes/enhancements/blob/master/keps/sig-cluster-lifecycle/wgs/0032-create-a-k8s-io-component-repo.md + +The proposal is essentially about refactoring the Kubernetes core package structure in a way that all core components may share common code around: + - ComponentConfig implementation + - flag and command handling + - HTTPS serving + - delegated authn/z + - logging. + +## Compatibility + +There are *NO compatibility guarantees* for this repository, yet. It is in direct support of Kubernetes, so branches +will track Kubernetes and be compatible with that repo. As we more cleanly separate the layers, we will review the +compatibility guarantee. We have a goal to make this easier to use in the future. + + +## Where does it come from? + +This repository is synced from https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/component-base. +Code changes are made in that location, merged into `k8s.io/kubernetes` and later synced here. + +## Things you should *NOT* do + + 1. Directly modify any files in this repo. Those are driven from `k8s.io/kubernetes/staging/src/k8s.io/component-base`. + 2. Expect compatibility. This repo is changing quickly in direct support of Kubernetes. + +### OWNERS + +WG Component Standard is working on this refactoring process, which is happening incrementally, starting in the v1.14 cycle. +SIG API Machinery and SIG Cluster Lifecycle owns the code. diff --git a/vendor/k8s.io/component-base/go.mod b/vendor/k8s.io/component-base/go.mod new file mode 100644 index 000000000..81833c480 --- /dev/null +++ b/vendor/k8s.io/component-base/go.mod @@ -0,0 +1,33 @@ +// This is a generated file. Do not edit directly. + +module k8s.io/component-base + +go 1.15 + +require ( + github.com/blang/semver v3.5.0+incompatible + github.com/go-logr/logr v0.2.0 + github.com/google/go-cmp v0.4.0 + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/moby/term v0.0.0-20200312100748-672ec06f55cd + github.com/prometheus/client_golang v1.7.1 + github.com/prometheus/client_model v0.2.0 + github.com/prometheus/common v0.10.0 + github.com/prometheus/procfs v0.1.3 + github.com/sirupsen/logrus v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.4.0 + go.uber.org/atomic v1.4.0 // indirect + go.uber.org/multierr v1.1.0 // indirect + go.uber.org/zap v1.10.0 + k8s.io/apimachinery v0.19.2 + k8s.io/client-go v0.19.2 + k8s.io/klog/v2 v2.2.0 + k8s.io/utils v0.0.0-20200729134348-d5654de09c73 +) + +replace ( + k8s.io/api => k8s.io/api v0.19.2 + k8s.io/apimachinery => k8s.io/apimachinery v0.19.2 + k8s.io/client-go => k8s.io/client-go v0.19.2 +) diff --git a/vendor/k8s.io/component-base/logs/logreduction/logreduction.go b/vendor/k8s.io/component-base/logs/logreduction/logreduction.go new file mode 100644 index 000000000..6534a5a64 --- /dev/null +++ b/vendor/k8s.io/component-base/logs/logreduction/logreduction.go @@ -0,0 +1,78 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logreduction + +import ( + "sync" + "time" +) + +var nowfunc = func() time.Time { return time.Now() } + +// LogReduction provides a filter for consecutive identical log messages; +// a message will be printed no more than once per interval. +// If a string of messages is interrupted by a different message, +// the interval timer will be reset. +type LogReduction struct { + lastError map[string]string + errorPrinted map[string]time.Time + errorMapLock sync.Mutex + identicalErrorDelay time.Duration +} + +// NewLogReduction returns an initialized LogReduction +func NewLogReduction(identicalErrorDelay time.Duration) *LogReduction { + l := new(LogReduction) + l.lastError = make(map[string]string) + l.errorPrinted = make(map[string]time.Time) + l.identicalErrorDelay = identicalErrorDelay + return l +} + +func (l *LogReduction) cleanupErrorTimeouts() { + for name, timeout := range l.errorPrinted { + if nowfunc().Sub(timeout) >= l.identicalErrorDelay { + delete(l.errorPrinted, name) + delete(l.lastError, name) + } + } +} + +// ShouldMessageBePrinted determines whether a message should be printed based +// on how long ago this particular message was last printed +func (l *LogReduction) ShouldMessageBePrinted(message string, parentID string) bool { + l.errorMapLock.Lock() + defer l.errorMapLock.Unlock() + l.cleanupErrorTimeouts() + lastMsg, ok := l.lastError[parentID] + lastPrinted, ok1 := l.errorPrinted[parentID] + if !ok || !ok1 || message != lastMsg || nowfunc().Sub(lastPrinted) >= l.identicalErrorDelay { + l.errorPrinted[parentID] = nowfunc() + l.lastError[parentID] = message + return true + } + return false +} + +// ClearID clears out log reduction records pertaining to a particular parent +// (e. g. container ID) +func (l *LogReduction) ClearID(parentID string) { + l.errorMapLock.Lock() + defer l.errorMapLock.Unlock() + delete(l.lastError, parentID) + delete(l.errorPrinted, parentID) +} diff --git a/vendor/k8s.io/cri-api/pkg/apis/services.go b/vendor/k8s.io/cri-api/pkg/apis/services.go new file mode 100644 index 000000000..9a22ecbf0 --- /dev/null +++ b/vendor/k8s.io/cri-api/pkg/apis/services.go @@ -0,0 +1,119 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cri + +import ( + "time" + + runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" +) + +// RuntimeVersioner contains methods for runtime name, version and API version. +type RuntimeVersioner interface { + // Version returns the runtime name, runtime version and runtime API version + Version(apiVersion string) (*runtimeapi.VersionResponse, error) +} + +// ContainerManager contains methods to manipulate containers managed by a +// container runtime. The methods are thread-safe. +type ContainerManager interface { + // CreateContainer creates a new container in specified PodSandbox. + CreateContainer(podSandboxID string, config *runtimeapi.ContainerConfig, sandboxConfig *runtimeapi.PodSandboxConfig) (string, error) + // StartContainer starts the container. + StartContainer(containerID string) error + // StopContainer stops a running container with a grace period (i.e., timeout). + StopContainer(containerID string, timeout int64) error + // RemoveContainer removes the container. + RemoveContainer(containerID string) error + // ListContainers lists all containers by filters. + ListContainers(filter *runtimeapi.ContainerFilter) ([]*runtimeapi.Container, error) + // ContainerStatus returns the status of the container. + ContainerStatus(containerID string) (*runtimeapi.ContainerStatus, error) + // UpdateContainerResources updates the cgroup resources for the container. + UpdateContainerResources(containerID string, resources *runtimeapi.LinuxContainerResources) error + // ExecSync executes a command in the container, and returns the stdout output. + // If command exits with a non-zero exit code, an error is returned. + ExecSync(containerID string, cmd []string, timeout time.Duration) (stdout []byte, stderr []byte, err error) + // Exec prepares a streaming endpoint to execute a command in the container, and returns the address. + Exec(*runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error) + // Attach prepares a streaming endpoint to attach to a running container, and returns the address. + Attach(req *runtimeapi.AttachRequest) (*runtimeapi.AttachResponse, error) + // ReopenContainerLog asks runtime to reopen the stdout/stderr log file + // for the container. If it returns error, new container log file MUST NOT + // be created. + ReopenContainerLog(ContainerID string) error +} + +// PodSandboxManager contains methods for operating on PodSandboxes. The methods +// are thread-safe. +type PodSandboxManager interface { + // RunPodSandbox creates and starts a pod-level sandbox. Runtimes should ensure + // the sandbox is in ready state. + RunPodSandbox(config *runtimeapi.PodSandboxConfig, runtimeHandler string) (string, error) + // StopPodSandbox stops the sandbox. If there are any running containers in the + // sandbox, they should be force terminated. + StopPodSandbox(podSandboxID string) error + // RemovePodSandbox removes the sandbox. If there are running containers in the + // sandbox, they should be forcibly removed. + RemovePodSandbox(podSandboxID string) error + // PodSandboxStatus returns the Status of the PodSandbox. + PodSandboxStatus(podSandboxID string) (*runtimeapi.PodSandboxStatus, error) + // ListPodSandbox returns a list of Sandbox. + ListPodSandbox(filter *runtimeapi.PodSandboxFilter) ([]*runtimeapi.PodSandbox, error) + // PortForward prepares a streaming endpoint to forward ports from a PodSandbox, and returns the address. + PortForward(*runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error) +} + +// ContainerStatsManager contains methods for retrieving the container +// statistics. +type ContainerStatsManager interface { + // ContainerStats returns stats of the container. If the container does not + // exist, the call returns an error. + ContainerStats(containerID string) (*runtimeapi.ContainerStats, error) + // ListContainerStats returns stats of all running containers. + ListContainerStats(filter *runtimeapi.ContainerStatsFilter) ([]*runtimeapi.ContainerStats, error) +} + +// RuntimeService interface should be implemented by a container runtime. +// The methods should be thread-safe. +type RuntimeService interface { + RuntimeVersioner + ContainerManager + PodSandboxManager + ContainerStatsManager + + // UpdateRuntimeConfig updates runtime configuration if specified + UpdateRuntimeConfig(runtimeConfig *runtimeapi.RuntimeConfig) error + // Status returns the status of the runtime. + Status() (*runtimeapi.RuntimeStatus, error) +} + +// ImageManagerService interface should be implemented by a container image +// manager. +// The methods should be thread-safe. +type ImageManagerService interface { + // ListImages lists the existing images. + ListImages(filter *runtimeapi.ImageFilter) ([]*runtimeapi.Image, error) + // ImageStatus returns the status of the image. + ImageStatus(image *runtimeapi.ImageSpec) (*runtimeapi.Image, error) + // PullImage pulls an image with the authentication config. + PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error) + // RemoveImage removes the image. + RemoveImage(image *runtimeapi.ImageSpec) error + // ImageFsInfo returns information of the filesystem that is used to store images. + ImageFsInfo() ([]*runtimeapi.FilesystemUsage, error) +}