mirror of https://github.com/linkerd/linkerd2.git
Simplify SelfCheck API (#5665)
Fixes #5575 Now that only viz makes use of the `SelfCheck` api, merged the `healthcheck.proto` into `viz.proto`. Also removed the "checkRPC" functionality that was used for handling multiple API responses and was only used by `SelfCheck`, because the extra complexity was not granted. Revert to use the plain vanilla "check" by just concatenating error responses. ## Success Output ```bash $ bin/linkerd viz check ... linkerd-viz ----------- ... √ viz extension self-check ``` ## Failure Examples Failure when viz fails to connect to the k8s api: ```bash $ bin/linkerd viz check ... linkerd-viz ----------- ... × viz extension self-check Error calling the Kubernetes API: someerror see https://linkerd.io/checks/#l5d-api-control-api for hints Status check results are × ``` Failure when viz fails to connect to Prometheus: ```bash $ bin/linkerd viz check ... linkerd-viz ----------- ... × viz extension self-check Error calling Prometheus from the control plane: someerror see https://linkerd.io/checks/#l5d-api-control-api for hints Status check results are × ``` Failure when viz fails to connect to both the k8s api and Prometheus: ```bash $ bin/linkerd viz check ... linkerd-viz ----------- ... × viz extension self-check Error calling the Kubernetes API: someerror Error calling Prometheus from the control plane: someerror see https://linkerd.io/checks/#l5d-api-control-api for hints Status check results are × ```
This commit is contained in:
parent
704ed00a49
commit
a04b30d2ab
|
@ -7,16 +7,14 @@ bindir=$( cd "${0%/*}" && pwd )
|
||||||
go install -mod=readonly github.com/golang/protobuf/protoc-gen-go
|
go install -mod=readonly github.com/golang/protobuf/protoc-gen-go
|
||||||
|
|
||||||
rm -rf controller/gen/common controller/gen/public controller/gen/config viz/metrics-api/gen
|
rm -rf controller/gen/common controller/gen/public controller/gen/config viz/metrics-api/gen
|
||||||
mkdir -p controller/gen/common/healthcheck controller/gen/common/net controller/gen/public viz/metrics-api/gen/viz
|
mkdir -p controller/gen/common/net controller/gen/public viz/metrics-api/gen/viz
|
||||||
|
|
||||||
"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/common/net.proto
|
"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/common/net.proto
|
||||||
"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/public.proto
|
"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/public.proto
|
||||||
"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/config/config.proto
|
"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/config/config.proto
|
||||||
"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/common/healthcheck.proto
|
|
||||||
"$bindir"/protoc -I proto -I viz/metrics-api/proto --go_out=plugins=grpc,paths=source_relative:viz/metrics-api/gen viz/metrics-api/proto/viz.proto
|
"$bindir"/protoc -I proto -I viz/metrics-api/proto --go_out=plugins=grpc,paths=source_relative:viz/metrics-api/gen viz/metrics-api/proto/viz.proto
|
||||||
|
|
||||||
mv controller/gen/common/net.pb.go controller/gen/common/net/
|
mv controller/gen/common/net.pb.go controller/gen/common/net/
|
||||||
mv controller/gen/public.pb.go controller/gen/public/
|
mv controller/gen/public.pb.go controller/gen/public/
|
||||||
mv controller/gen/common/healthcheck.pb.go controller/gen/common/healthcheck/
|
|
||||||
mv viz/metrics-api/gen/viz.pb.go viz/metrics-api/gen/viz/viz.pb.go
|
mv viz/metrics-api/gen/viz.pb.go viz/metrics-api/gen/viz/viz.pb.go
|
||||||
|
|
||||||
|
|
|
@ -1,362 +0,0 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.24.0
|
|
||||||
// protoc v3.6.0
|
|
||||||
// source: common/healthcheck.proto
|
|
||||||
|
|
||||||
package healthcheck
|
|
||||||
|
|
||||||
import (
|
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Verify that this generated code is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
|
||||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type CheckStatus int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
CheckStatus_OK CheckStatus = 0
|
|
||||||
CheckStatus_FAIL CheckStatus = 1
|
|
||||||
CheckStatus_ERROR CheckStatus = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for CheckStatus.
|
|
||||||
var (
|
|
||||||
CheckStatus_name = map[int32]string{
|
|
||||||
0: "OK",
|
|
||||||
1: "FAIL",
|
|
||||||
2: "ERROR",
|
|
||||||
}
|
|
||||||
CheckStatus_value = map[string]int32{
|
|
||||||
"OK": 0,
|
|
||||||
"FAIL": 1,
|
|
||||||
"ERROR": 2,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x CheckStatus) Enum() *CheckStatus {
|
|
||||||
p := new(CheckStatus)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x CheckStatus) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (CheckStatus) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_common_healthcheck_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (CheckStatus) Type() protoreflect.EnumType {
|
|
||||||
return &file_common_healthcheck_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x CheckStatus) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use CheckStatus.Descriptor instead.
|
|
||||||
func (CheckStatus) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_common_healthcheck_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CheckResult struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
SubsystemName string `protobuf:"bytes,1,opt,name=SubsystemName,proto3" json:"SubsystemName,omitempty"`
|
|
||||||
CheckDescription string `protobuf:"bytes,2,opt,name=CheckDescription,proto3" json:"CheckDescription,omitempty"`
|
|
||||||
Status CheckStatus `protobuf:"varint,3,opt,name=Status,proto3,enum=linkerd2.common.healthcheck.CheckStatus" json:"Status,omitempty"`
|
|
||||||
FriendlyMessageToUser string `protobuf:"bytes,4,opt,name=FriendlyMessageToUser,proto3" json:"FriendlyMessageToUser,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CheckResult) Reset() {
|
|
||||||
*x = CheckResult{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_healthcheck_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CheckResult) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*CheckResult) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *CheckResult) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_healthcheck_proto_msgTypes[0]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use CheckResult.ProtoReflect.Descriptor instead.
|
|
||||||
func (*CheckResult) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_healthcheck_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CheckResult) GetSubsystemName() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.SubsystemName
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CheckResult) GetCheckDescription() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.CheckDescription
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CheckResult) GetStatus() CheckStatus {
|
|
||||||
if x != nil {
|
|
||||||
return x.Status
|
|
||||||
}
|
|
||||||
return CheckStatus_OK
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CheckResult) GetFriendlyMessageToUser() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.FriendlyMessageToUser
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type SelfCheckRequest struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SelfCheckRequest) Reset() {
|
|
||||||
*x = SelfCheckRequest{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_healthcheck_proto_msgTypes[1]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SelfCheckRequest) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*SelfCheckRequest) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *SelfCheckRequest) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_healthcheck_proto_msgTypes[1]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use SelfCheckRequest.ProtoReflect.Descriptor instead.
|
|
||||||
func (*SelfCheckRequest) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_healthcheck_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
type SelfCheckResponse struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Results []*CheckResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SelfCheckResponse) Reset() {
|
|
||||||
*x = SelfCheckResponse{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_healthcheck_proto_msgTypes[2]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SelfCheckResponse) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*SelfCheckResponse) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *SelfCheckResponse) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_healthcheck_proto_msgTypes[2]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use SelfCheckResponse.ProtoReflect.Descriptor instead.
|
|
||||||
func (*SelfCheckResponse) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_healthcheck_proto_rawDescGZIP(), []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SelfCheckResponse) GetResults() []*CheckResult {
|
|
||||||
if x != nil {
|
|
||||||
return x.Results
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_common_healthcheck_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_common_healthcheck_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63,
|
|
||||||
0x68, 0x65, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x6c, 0x69, 0x6e, 0x6b,
|
|
||||||
0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x68, 0x65, 0x61, 0x6c,
|
|
||||||
0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xd7, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63,
|
|
||||||
0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x73, 0x79,
|
|
||||||
0x73, 0x74, 0x65, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
|
||||||
0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a,
|
|
||||||
0x10, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
|
||||||
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65,
|
|
||||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x06, 0x53, 0x74, 0x61,
|
|
||||||
0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x6c, 0x69, 0x6e, 0x6b,
|
|
||||||
0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x68, 0x65, 0x61, 0x6c,
|
|
||||||
0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x61,
|
|
||||||
0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x46,
|
|
||||||
0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x6f,
|
|
||||||
0x55, 0x73, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x46, 0x72, 0x69, 0x65,
|
|
||||||
0x6e, 0x64, 0x6c, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65,
|
|
||||||
0x72, 0x22, 0x12, 0x0a, 0x10, 0x53, 0x65, 0x6c, 0x66, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65,
|
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x57, 0x0a, 0x11, 0x53, 0x65, 0x6c, 0x66, 0x43, 0x68, 0x65,
|
|
||||||
0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x07, 0x72, 0x65,
|
|
||||||
0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6c, 0x69,
|
|
||||||
0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x68, 0x65,
|
|
||||||
0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52,
|
|
||||||
0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2a, 0x2a,
|
|
||||||
0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x06, 0x0a,
|
|
||||||
0x02, 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x01, 0x12,
|
|
||||||
0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69,
|
|
||||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64,
|
|
||||||
0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
|
||||||
0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f,
|
|
||||||
0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_common_healthcheck_proto_rawDescOnce sync.Once
|
|
||||||
file_common_healthcheck_proto_rawDescData = file_common_healthcheck_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_common_healthcheck_proto_rawDescGZIP() []byte {
|
|
||||||
file_common_healthcheck_proto_rawDescOnce.Do(func() {
|
|
||||||
file_common_healthcheck_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_healthcheck_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_common_healthcheck_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_common_healthcheck_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
|
||||||
var file_common_healthcheck_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
|
||||||
var file_common_healthcheck_proto_goTypes = []interface{}{
|
|
||||||
(CheckStatus)(0), // 0: linkerd2.common.healthcheck.CheckStatus
|
|
||||||
(*CheckResult)(nil), // 1: linkerd2.common.healthcheck.CheckResult
|
|
||||||
(*SelfCheckRequest)(nil), // 2: linkerd2.common.healthcheck.SelfCheckRequest
|
|
||||||
(*SelfCheckResponse)(nil), // 3: linkerd2.common.healthcheck.SelfCheckResponse
|
|
||||||
}
|
|
||||||
var file_common_healthcheck_proto_depIdxs = []int32{
|
|
||||||
0, // 0: linkerd2.common.healthcheck.CheckResult.Status:type_name -> linkerd2.common.healthcheck.CheckStatus
|
|
||||||
1, // 1: linkerd2.common.healthcheck.SelfCheckResponse.results:type_name -> linkerd2.common.healthcheck.CheckResult
|
|
||||||
2, // [2:2] is the sub-list for method output_type
|
|
||||||
2, // [2:2] is the sub-list for method input_type
|
|
||||||
2, // [2:2] is the sub-list for extension type_name
|
|
||||||
2, // [2:2] is the sub-list for extension extendee
|
|
||||||
0, // [0:2] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_common_healthcheck_proto_init() }
|
|
||||||
func file_common_healthcheck_proto_init() {
|
|
||||||
if File_common_healthcheck_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_common_healthcheck_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*CheckResult); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_common_healthcheck_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*SelfCheckRequest); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_common_healthcheck_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*SelfCheckResponse); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type x struct{}
|
|
||||||
out := protoimpl.TypeBuilder{
|
|
||||||
File: protoimpl.DescBuilder{
|
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
||||||
RawDescriptor: file_common_healthcheck_proto_rawDesc,
|
|
||||||
NumEnums: 1,
|
|
||||||
NumMessages: 3,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 0,
|
|
||||||
},
|
|
||||||
GoTypes: file_common_healthcheck_proto_goTypes,
|
|
||||||
DependencyIndexes: file_common_healthcheck_proto_depIdxs,
|
|
||||||
EnumInfos: file_common_healthcheck_proto_enumTypes,
|
|
||||||
MessageInfos: file_common_healthcheck_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_common_healthcheck_proto = out.File
|
|
||||||
file_common_healthcheck_proto_rawDesc = nil
|
|
||||||
file_common_healthcheck_proto_goTypes = nil
|
|
||||||
file_common_healthcheck_proto_depIdxs = nil
|
|
||||||
}
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/linkerd/linkerd2/controller/api/public"
|
"github.com/linkerd/linkerd2/controller/api/public"
|
||||||
healthcheckPb "github.com/linkerd/linkerd2/controller/gen/common/healthcheck"
|
|
||||||
configPb "github.com/linkerd/linkerd2/controller/gen/config"
|
configPb "github.com/linkerd/linkerd2/controller/gen/config"
|
||||||
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
|
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
|
||||||
"github.com/linkerd/linkerd2/pkg/config"
|
"github.com/linkerd/linkerd2/pkg/config"
|
||||||
|
@ -304,11 +303,6 @@ type Checker struct {
|
||||||
// check is the function that's called to execute the check; if the function
|
// check is the function that's called to execute the check; if the function
|
||||||
// returns an error, the check fails
|
// returns an error, the check fails
|
||||||
check func(context.Context) error
|
check func(context.Context) error
|
||||||
|
|
||||||
// checkRPC is an alternative to check that can be used to perform a remote
|
|
||||||
// check using the SelfCheck gRPC endpoint; check status is based on the value
|
|
||||||
// of the gRPC response
|
|
||||||
checkRPC func(context.Context) (*healthcheckPb.SelfCheckResponse, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChecker returns a new instance of checker type
|
// NewChecker returns a new instance of checker type
|
||||||
|
@ -355,12 +349,6 @@ func (c *Checker) WithCheck(check func(context.Context) error) *Checker {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithCheckRPC returns a checker with the provided checkRPC func
|
|
||||||
func (c *Checker) WithCheckRPC(checkRPC func(context.Context) (*healthcheckPb.SelfCheckResponse, error)) *Checker {
|
|
||||||
c.checkRPC = checkRPC
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckResult encapsulates a check's identifying information and output
|
// CheckResult encapsulates a check's identifying information and output
|
||||||
// Note there exists an analogous user-facing type, `cmd.check`, for output via
|
// Note there exists an analogous user-facing type, `cmd.check`, for output via
|
||||||
// `linkerd check -o json`.
|
// `linkerd check -o json`.
|
||||||
|
@ -1477,17 +1465,6 @@ func (hc *HealthChecker) RunChecks(observer CheckObserver) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if checker.checkRPC != nil {
|
|
||||||
if !hc.runCheckRPC(c.ID, &checker, observer) {
|
|
||||||
if !checker.warning {
|
|
||||||
success = false
|
|
||||||
}
|
|
||||||
if checker.fatal {
|
|
||||||
return success
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1539,77 +1516,6 @@ func (hc *HealthChecker) runCheck(categoryID CategoryID, c *Checker, observer Ch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// runCheckRPC calls `c` which itself should make a gRPC call returning `*healthcheckPb.SelfCheckResponse`
|
|
||||||
// (which can contain multiple responses) or error.
|
|
||||||
// If that call returns an error, we send it to `observer` and return false.
|
|
||||||
// Otherwise, we send to `observer` a success message with `c.description` and then proceed to check the
|
|
||||||
// multiple responses contained in the response.
|
|
||||||
// We keep on retrying the same call until all the responses have an OK status
|
|
||||||
// (or until timeout/deadline is reached), sending a message to `observer` for each response,
|
|
||||||
// while making sure no duplicate messages are sent.
|
|
||||||
func (hc *HealthChecker) runCheckRPC(categoryID CategoryID, c *Checker, observer CheckObserver) bool {
|
|
||||||
observedResults := []CheckResult{}
|
|
||||||
for {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), RequestTimeout)
|
|
||||||
defer cancel()
|
|
||||||
checkRsp, err := c.checkRPC(ctx)
|
|
||||||
if se, ok := err.(*SkipError); ok {
|
|
||||||
log.Debugf("Skipping check: %s. Reason: %s", c.description, se.Reason)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
checkResult := &CheckResult{
|
|
||||||
Category: categoryID,
|
|
||||||
Description: c.description,
|
|
||||||
HintAnchor: c.hintAnchor,
|
|
||||||
Warning: c.warning,
|
|
||||||
}
|
|
||||||
|
|
||||||
if vs, ok := err.(*VerboseSuccess); ok {
|
|
||||||
checkResult.Description = fmt.Sprintf("%s\n%s", checkResult.Description, vs.Message)
|
|
||||||
} else if err != nil {
|
|
||||||
// errors at the gRPC-call level are not retried
|
|
||||||
// but we do retry below if the response Status is not OK
|
|
||||||
checkResult.Err = &CategoryError{categoryID, err}
|
|
||||||
observer(checkResult)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// General description, only shown once.
|
|
||||||
// The following calls to `observer()` track specific result entries.
|
|
||||||
if !checkResult.alreadyObserved(observedResults) {
|
|
||||||
observer(checkResult)
|
|
||||||
observedResults = append(observedResults, *checkResult)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, check := range checkRsp.Results {
|
|
||||||
checkResult.Err = nil
|
|
||||||
checkResult.Description = fmt.Sprintf("[%s] %s", check.SubsystemName, check.CheckDescription)
|
|
||||||
if check.Status != healthcheckPb.CheckStatus_OK {
|
|
||||||
checkResult.Err = &CategoryError{categoryID, fmt.Errorf(check.FriendlyMessageToUser)}
|
|
||||||
checkResult.Retry = time.Now().Before(c.retryDeadline)
|
|
||||||
// only show the waiting message during retries,
|
|
||||||
// and send the underlying error on the last try
|
|
||||||
if !c.surfaceErrorOnRetry && checkResult.Retry {
|
|
||||||
checkResult.Err = errors.New("waiting for check to complete")
|
|
||||||
}
|
|
||||||
observer(checkResult)
|
|
||||||
} else if !checkResult.alreadyObserved(observedResults) {
|
|
||||||
observer(checkResult)
|
|
||||||
}
|
|
||||||
observedResults = append(observedResults, *checkResult)
|
|
||||||
}
|
|
||||||
|
|
||||||
if checkResult.Retry {
|
|
||||||
log.Debug("Retrying on error")
|
|
||||||
time.Sleep(retryWindow)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkResult.Err == nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hc *HealthChecker) controlPlaneComponentsSelector() string {
|
func (hc *HealthChecker) controlPlaneComponentsSelector() string {
|
||||||
return fmt.Sprintf("%s,!%s", k8s.ControllerNSLabel, LinkerdCNIResourceLabel)
|
return fmt.Sprintf("%s,!%s", k8s.ControllerNSLabel, LinkerdCNIResourceLabel)
|
||||||
}
|
}
|
||||||
|
@ -2323,15 +2229,6 @@ func (hc *HealthChecker) checkClockSkew(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *CheckResult) alreadyObserved(previousResults []CheckResult) bool {
|
|
||||||
for _, result := range previousResults {
|
|
||||||
if result.Description == cr.Description && result.Err == cr.Err {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckRoles checks that the expected roles exist.
|
// CheckRoles checks that the expected roles exist.
|
||||||
func CheckRoles(ctx context.Context, kubeAPI *k8s.KubernetesAPI, shouldExist bool, namespace string, expectedNames []string, labelSelector string) error {
|
func CheckRoles(ctx context.Context, kubeAPI *k8s.KubernetesAPI, shouldExist bool, namespace string, expectedNames []string, labelSelector string) error {
|
||||||
options := metav1.ListOptions{
|
options := metav1.ListOptions{
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/ptypes/duration"
|
"github.com/golang/protobuf/ptypes/duration"
|
||||||
healthcheckPb "github.com/linkerd/linkerd2/controller/gen/common/healthcheck"
|
|
||||||
configPb "github.com/linkerd/linkerd2/controller/gen/config"
|
configPb "github.com/linkerd/linkerd2/controller/gen/config"
|
||||||
"github.com/linkerd/linkerd2/pkg/charts/linkerd2"
|
"github.com/linkerd/linkerd2/pkg/charts/linkerd2"
|
||||||
"github.com/linkerd/linkerd2/pkg/identity"
|
"github.com/linkerd/linkerd2/pkg/identity"
|
||||||
|
@ -148,8 +147,8 @@ func TestHealthChecker(t *testing.T) {
|
||||||
checkers: []Checker{
|
checkers: []Checker{
|
||||||
{
|
{
|
||||||
description: "skipRpc",
|
description: "skipRpc",
|
||||||
checkRPC: func(context.Context) (*healthcheckPb.SelfCheckResponse, error) {
|
check: func(context.Context) error {
|
||||||
return nil, &SkipError{Reason: "needs skipping"}
|
return &SkipError{Reason: "needs skipping"}
|
||||||
},
|
},
|
||||||
retryDeadline: time.Time{},
|
retryDeadline: time.Time{},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package linkerd2.common.healthcheck;
|
|
||||||
|
|
||||||
option go_package = "github.com/linkerd/linkerd2/controller/gen/common/healthcheck";
|
|
||||||
|
|
||||||
enum CheckStatus {
|
|
||||||
OK = 0;
|
|
||||||
FAIL = 1;
|
|
||||||
ERROR = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CheckResult {
|
|
||||||
string SubsystemName = 1;
|
|
||||||
string CheckDescription = 2;
|
|
||||||
CheckStatus Status = 3;
|
|
||||||
string FriendlyMessageToUser = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SelfCheckRequest {}
|
|
||||||
|
|
||||||
message SelfCheckResponse {
|
|
||||||
repeated CheckResult results = 1;
|
|
||||||
}
|
|
|
@ -27,7 +27,5 @@ linkerd-viz
|
||||||
√ grafana is installed and configured correctly
|
√ grafana is installed and configured correctly
|
||||||
√ can initialize the client
|
√ can initialize the client
|
||||||
√ viz extension self-check
|
√ viz extension self-check
|
||||||
√ [kubernetes] linkerd viz can talk to Kubernetes
|
|
||||||
√ [prometheus] linkerd viz can talk to Prometheus
|
|
||||||
|
|
||||||
Status check results are √
|
Status check results are √
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
healthcheckPb "github.com/linkerd/linkerd2/controller/gen/common/healthcheck"
|
|
||||||
"github.com/linkerd/linkerd2/pkg/k8s"
|
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||||
"github.com/linkerd/linkerd2/pkg/protohttp"
|
"github.com/linkerd/linkerd2/pkg/protohttp"
|
||||||
pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
|
pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
|
||||||
|
@ -62,8 +61,8 @@ func (c *grpcOverHTTPClient) Gateways(ctx context.Context, req *pb.GatewaysReque
|
||||||
return &msg, err
|
return &msg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *grpcOverHTTPClient) SelfCheck(ctx context.Context, req *healthcheckPb.SelfCheckRequest, _ ...grpc.CallOption) (*healthcheckPb.SelfCheckResponse, error) {
|
func (c *grpcOverHTTPClient) SelfCheck(ctx context.Context, req *pb.SelfCheckRequest, _ ...grpc.CallOption) (*pb.SelfCheckResponse, error) {
|
||||||
var msg healthcheckPb.SelfCheckResponse
|
var msg pb.SelfCheckResponse
|
||||||
err := c.apiRequest(ctx, "SelfCheck", req, &msg)
|
err := c.apiRequest(ctx, "SelfCheck", req, &msg)
|
||||||
return &msg, err
|
return &msg, err
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,7 +7,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/ptypes/duration"
|
"github.com/golang/protobuf/ptypes/duration"
|
||||||
healthcheckPb "github.com/linkerd/linkerd2/controller/gen/common/healthcheck"
|
|
||||||
"github.com/linkerd/linkerd2/controller/k8s"
|
"github.com/linkerd/linkerd2/controller/k8s"
|
||||||
pkgK8s "github.com/linkerd/linkerd2/pkg/k8s"
|
pkgK8s "github.com/linkerd/linkerd2/pkg/k8s"
|
||||||
"github.com/linkerd/linkerd2/pkg/prometheus"
|
"github.com/linkerd/linkerd2/pkg/prometheus"
|
||||||
|
@ -175,33 +174,33 @@ func (s *grpcServer) ListPods(ctx context.Context, req *pb.ListPodsRequest) (*pb
|
||||||
return &rsp, nil
|
return &rsp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *grpcServer) SelfCheck(ctx context.Context, in *healthcheckPb.SelfCheckRequest) (*healthcheckPb.SelfCheckResponse, error) {
|
func (s *grpcServer) SelfCheck(ctx context.Context, in *pb.SelfCheckRequest) (*pb.SelfCheckResponse, error) {
|
||||||
k8sClientCheck := &healthcheckPb.CheckResult{
|
k8sClientCheck := &pb.CheckResult{
|
||||||
SubsystemName: k8sClientSubsystemName,
|
SubsystemName: k8sClientSubsystemName,
|
||||||
CheckDescription: k8sClientCheckDescription,
|
CheckDescription: k8sClientCheckDescription,
|
||||||
Status: healthcheckPb.CheckStatus_OK,
|
Status: pb.CheckStatus_OK,
|
||||||
}
|
}
|
||||||
_, err := s.k8sAPI.Pod().Lister().List(labels.Everything())
|
_, err := s.k8sAPI.Pod().Lister().List(labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
k8sClientCheck.Status = healthcheckPb.CheckStatus_ERROR
|
k8sClientCheck.Status = pb.CheckStatus_ERROR
|
||||||
k8sClientCheck.FriendlyMessageToUser = fmt.Sprintf("Error calling the Kubernetes API: %s", err)
|
k8sClientCheck.FriendlyMessageToUser = fmt.Sprintf("Error calling the Kubernetes API: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
response := &healthcheckPb.SelfCheckResponse{
|
response := &pb.SelfCheckResponse{
|
||||||
Results: []*healthcheckPb.CheckResult{
|
Results: []*pb.CheckResult{
|
||||||
k8sClientCheck,
|
k8sClientCheck,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.prometheusAPI != nil {
|
if s.prometheusAPI != nil {
|
||||||
promClientCheck := &healthcheckPb.CheckResult{
|
promClientCheck := &pb.CheckResult{
|
||||||
SubsystemName: promClientSubsystemName,
|
SubsystemName: promClientSubsystemName,
|
||||||
CheckDescription: promClientCheckDescription,
|
CheckDescription: promClientCheckDescription,
|
||||||
Status: healthcheckPb.CheckStatus_OK,
|
Status: pb.CheckStatus_OK,
|
||||||
}
|
}
|
||||||
_, err = s.queryProm(ctx, fmt.Sprintf(podQuery, ""))
|
_, err = s.queryProm(ctx, fmt.Sprintf(podQuery, ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
promClientCheck.Status = healthcheckPb.CheckStatus_ERROR
|
promClientCheck.Status = pb.CheckStatus_ERROR
|
||||||
promClientCheck.FriendlyMessageToUser = fmt.Sprintf("Error calling Prometheus from the control plane: %s", err)
|
promClientCheck.FriendlyMessageToUser = fmt.Sprintf("Error calling Prometheus from the control plane: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
healthcheckPb "github.com/linkerd/linkerd2/controller/gen/common/healthcheck"
|
|
||||||
"github.com/linkerd/linkerd2/controller/k8s"
|
"github.com/linkerd/linkerd2/controller/k8s"
|
||||||
"github.com/linkerd/linkerd2/pkg/prometheus"
|
"github.com/linkerd/linkerd2/pkg/prometheus"
|
||||||
"github.com/linkerd/linkerd2/pkg/protohttp"
|
"github.com/linkerd/linkerd2/pkg/protohttp"
|
||||||
|
@ -146,7 +145,7 @@ func (h *handler) handleTopRoutes(w http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) handleSelfCheck(w http.ResponseWriter, req *http.Request) {
|
func (h *handler) handleSelfCheck(w http.ResponseWriter, req *http.Request) {
|
||||||
var protoRequest healthcheckPb.SelfCheckRequest
|
var protoRequest pb.SelfCheckRequest
|
||||||
err := protohttp.HTTPRequestToProto(req, &protoRequest)
|
err := protohttp.HTTPRequestToProto(req, &protoRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
protohttp.WriteErrorToHTTPResponse(w, err)
|
protohttp.WriteErrorToHTTPResponse(w, err)
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
healthcheckPb "github.com/linkerd/linkerd2/controller/gen/common/healthcheck"
|
|
||||||
vizClient "github.com/linkerd/linkerd2/viz/metrics-api/client"
|
vizClient "github.com/linkerd/linkerd2/viz/metrics-api/client"
|
||||||
pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
|
pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
|
||||||
)
|
)
|
||||||
|
@ -53,9 +52,9 @@ func (m *mockGrpcServer) ListServices(ctx context.Context, req *pb.ListServicesR
|
||||||
return m.ResponseToReturn.(*pb.ListServicesResponse), m.ErrorToReturn
|
return m.ResponseToReturn.(*pb.ListServicesResponse), m.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockGrpcServer) SelfCheck(ctx context.Context, req *healthcheckPb.SelfCheckRequest) (*healthcheckPb.SelfCheckResponse, error) {
|
func (m *mockGrpcServer) SelfCheck(ctx context.Context, req *pb.SelfCheckRequest) (*pb.SelfCheckResponse, error) {
|
||||||
m.LastRequestReceived = req
|
m.LastRequestReceived = req
|
||||||
return m.ResponseToReturn.(*healthcheckPb.SelfCheckResponse), m.ErrorToReturn
|
return m.ResponseToReturn.(*pb.SelfCheckResponse), m.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
type grpcCallTestCase struct {
|
type grpcCallTestCase struct {
|
||||||
|
|
|
@ -3,13 +3,31 @@ syntax = "proto3";
|
||||||
package linkerd2.viz;
|
package linkerd2.viz;
|
||||||
|
|
||||||
import "google/protobuf/duration.proto";
|
import "google/protobuf/duration.proto";
|
||||||
import "common/healthcheck.proto";
|
|
||||||
import "common/net.proto";
|
import "common/net.proto";
|
||||||
|
|
||||||
option go_package = "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz";
|
option go_package = "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz";
|
||||||
|
|
||||||
message Empty {}
|
message Empty {}
|
||||||
|
|
||||||
|
enum CheckStatus {
|
||||||
|
OK = 0;
|
||||||
|
FAIL = 1;
|
||||||
|
ERROR = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CheckResult {
|
||||||
|
string SubsystemName = 1;
|
||||||
|
string CheckDescription = 2;
|
||||||
|
CheckStatus Status = 3;
|
||||||
|
string FriendlyMessageToUser = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SelfCheckRequest {}
|
||||||
|
|
||||||
|
message SelfCheckResponse {
|
||||||
|
repeated CheckResult results = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message ListServicesRequest {
|
message ListServicesRequest {
|
||||||
string namespace = 1;
|
string namespace = 1;
|
||||||
}
|
}
|
||||||
|
@ -504,7 +522,7 @@ service Api {
|
||||||
|
|
||||||
rpc ListServices(ListServicesRequest) returns (ListServicesResponse) {}
|
rpc ListServices(ListServicesRequest) returns (ListServicesResponse) {}
|
||||||
|
|
||||||
rpc SelfCheck(linkerd2.common.healthcheck.SelfCheckRequest) returns (linkerd2.common.healthcheck.SelfCheckResponse) {}
|
rpc SelfCheck(SelfCheckRequest) returns (SelfCheckResponse) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
healthcheckPb "github.com/linkerd/linkerd2/controller/gen/common/healthcheck"
|
|
||||||
"github.com/linkerd/linkerd2/controller/k8s"
|
"github.com/linkerd/linkerd2/controller/k8s"
|
||||||
pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
|
pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
|
||||||
promv1 "github.com/prometheus/client_golang/api/prometheus/v1"
|
promv1 "github.com/prometheus/client_golang/api/prometheus/v1"
|
||||||
|
@ -25,7 +24,7 @@ type MockAPIClient struct {
|
||||||
GatewaysResponseToReturn *pb.GatewaysResponse
|
GatewaysResponseToReturn *pb.GatewaysResponse
|
||||||
TopRoutesResponseToReturn *pb.TopRoutesResponse
|
TopRoutesResponseToReturn *pb.TopRoutesResponse
|
||||||
EdgesResponseToReturn *pb.EdgesResponse
|
EdgesResponseToReturn *pb.EdgesResponse
|
||||||
SelfCheckResponseToReturn *healthcheckPb.SelfCheckResponse
|
SelfCheckResponseToReturn *pb.SelfCheckResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatSummary provides a mock of a Public API method.
|
// StatSummary provides a mock of a Public API method.
|
||||||
|
@ -59,7 +58,7 @@ func (c *MockAPIClient) ListServices(ctx context.Context, in *pb.ListServicesReq
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelfCheck provides a mock of a Public API method.
|
// SelfCheck provides a mock of a Public API method.
|
||||||
func (c *MockAPIClient) SelfCheck(ctx context.Context, in *healthcheckPb.SelfCheckRequest, _ ...grpc.CallOption) (*healthcheckPb.SelfCheckResponse, error) {
|
func (c *MockAPIClient) SelfCheck(ctx context.Context, in *pb.SelfCheckRequest, _ ...grpc.CallOption) (*pb.SelfCheckResponse, error) {
|
||||||
return c.SelfCheckResponseToReturn, c.ErrorToReturn
|
return c.SelfCheckResponseToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@ package healthcheck
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
healthcheckPb "github.com/linkerd/linkerd2/controller/gen/common/healthcheck"
|
|
||||||
"github.com/linkerd/linkerd2/pkg/healthcheck"
|
"github.com/linkerd/linkerd2/pkg/healthcheck"
|
||||||
"github.com/linkerd/linkerd2/pkg/k8s"
|
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||||
"github.com/linkerd/linkerd2/pkg/tls"
|
"github.com/linkerd/linkerd2/pkg/tls"
|
||||||
|
@ -233,8 +233,28 @@ func (hc *HealthChecker) VizCategory() healthcheck.Category {
|
||||||
// "waiting for check to complete" while things converge. If after the timeout
|
// "waiting for check to complete" while things converge. If after the timeout
|
||||||
// it still hasn't converged, we show the real error (a 503 usually).
|
// it still hasn't converged, we show the real error (a 503 usually).
|
||||||
WithRetryDeadline(hc.RetryDeadline).
|
WithRetryDeadline(hc.RetryDeadline).
|
||||||
WithCheckRPC(func(ctx context.Context) (*healthcheckPb.SelfCheckResponse, error) {
|
WithCheck(func(ctx context.Context) error {
|
||||||
return hc.vizAPIClient.SelfCheck(ctx, &healthcheckPb.SelfCheckRequest{})
|
results, err := hc.vizAPIClient.SelfCheck(ctx, &pb.SelfCheckRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(results.GetResults()) == 0 {
|
||||||
|
return errors.New("No results returned")
|
||||||
|
}
|
||||||
|
|
||||||
|
errs := []string{}
|
||||||
|
for _, res := range results.GetResults() {
|
||||||
|
if res.GetStatus() != pb.CheckStatus_OK {
|
||||||
|
errs = append(errs, res.GetFriendlyMessageToUser())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(errs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
errsStr := strings.Join(errs, "\n ")
|
||||||
|
return errors.New(errsStr)
|
||||||
}),
|
}),
|
||||||
}, true)
|
}, true)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue