mirror of https://github.com/linkerd/linkerd2.git
Enable lint check for comments (#2023)
Commit 1: Enable lint check for comments Part of #217. Follow up from #1982 and #2018. A subsequent commit will fix the ci failure. Commit 2: Address all comment-related linter errors. This change addresses all comment-related linter errors by doing the following: - Add comments to exported symbols - Make some exported symbols private - Recommend via TODOs that some exported symbols should should move or be removed This PR does not: - Modify, move, or remove any code - Modify existing comments Signed-off-by: Andrew Seigner <siggy@buoyant.io>
This commit is contained in:
parent
ef02cd6828
commit
1c302182ef
4
bin/lint
4
bin/lint
|
@ -12,8 +12,8 @@ cd "$rootdir"
|
||||||
# install golint from vendor
|
# install golint from vendor
|
||||||
go install ./vendor/golang.org/x/lint/golint
|
go install ./vendor/golang.org/x/lint/golint
|
||||||
|
|
||||||
# use `go list` to exclude packages in vendor, ignore uncommented warnings
|
# use `go list` to exclude packages in vendor
|
||||||
out=$(go list ./... | xargs golint | grep -v 'should have comment') || true
|
out=$(go list ./... | xargs golint) || true
|
||||||
|
|
||||||
if [ -n "$out" ]; then
|
if [ -n "$out" ]; then
|
||||||
echo "$out"
|
echo "$out"
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewClient creates a new gRPC client to the Destination service.
|
||||||
|
// TODO: consider moving this into destination-client, or removing altogether.
|
||||||
func NewClient(addr string) (pb.DestinationClient, *grpc.ClientConn, error) {
|
func NewClient(addr string) (pb.DestinationClient, *grpc.ClientConn, error) {
|
||||||
conn, err := grpc.Dial(addr, grpc.WithInsecure())
|
conn, err := grpc.Dial(addr, grpc.WithInsecure())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -190,6 +190,8 @@ func newClient(apiURL *url.URL, httpClientToUse *http.Client, controlPlaneNamesp
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewInternalClient creates a new Public API client intended to run inside a
|
||||||
|
// Kubernetes cluster.
|
||||||
func NewInternalClient(controlPlaneNamespace string, kubeAPIHost string) (pb.ApiClient, error) {
|
func NewInternalClient(controlPlaneNamespace string, kubeAPIHost string) (pb.ApiClient, error) {
|
||||||
apiURL, err := url.Parse(fmt.Sprintf("http://%s/", kubeAPIHost))
|
apiURL, err := url.Parse(fmt.Sprintf("http://%s/", kubeAPIHost))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -199,6 +201,8 @@ func NewInternalClient(controlPlaneNamespace string, kubeAPIHost string) (pb.Api
|
||||||
return newClient(apiURL, http.DefaultClient, controlPlaneNamespace)
|
return newClient(apiURL, http.DefaultClient, controlPlaneNamespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewExternalClient creates a new Public API client intended to run from
|
||||||
|
// outside a Kubernetes cluster.
|
||||||
func NewExternalClient(controlPlaneNamespace string, kubeAPI *k8s.KubernetesAPI) (pb.ApiClient, error) {
|
func NewExternalClient(controlPlaneNamespace string, kubeAPI *k8s.KubernetesAPI) (pb.ApiClient, error) {
|
||||||
apiURL, err := kubeAPI.URLFor(controlPlaneNamespace, "/services/linkerd-controller-api:http/proxy/")
|
apiURL, err := kubeAPI.URLFor(controlPlaneNamespace, "/services/linkerd-controller-api:http/proxy/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -39,10 +39,10 @@ type podReport struct {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
podQuery = "max(process_start_time_seconds{%s}) by (pod, namespace)"
|
podQuery = "max(process_start_time_seconds{%s}) by (pod, namespace)"
|
||||||
K8sClientSubsystemName = "kubernetes"
|
k8sClientSubsystemName = "kubernetes"
|
||||||
K8sClientCheckDescription = "control plane can talk to Kubernetes"
|
k8sClientCheckDescription = "control plane can talk to Kubernetes"
|
||||||
PromClientSubsystemName = "prometheus"
|
promClientSubsystemName = "prometheus"
|
||||||
PromClientCheckDescription = "control plane can talk to Prometheus"
|
promClientCheckDescription = "control plane can talk to Prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newGrpcServer(
|
func newGrpcServer(
|
||||||
|
@ -190,8 +190,8 @@ func (s *grpcServer) ListPods(ctx context.Context, req *pb.ListPodsRequest) (*pb
|
||||||
|
|
||||||
func (s *grpcServer) SelfCheck(ctx context.Context, in *healthcheckPb.SelfCheckRequest) (*healthcheckPb.SelfCheckResponse, error) {
|
func (s *grpcServer) SelfCheck(ctx context.Context, in *healthcheckPb.SelfCheckRequest) (*healthcheckPb.SelfCheckResponse, error) {
|
||||||
k8sClientCheck := &healthcheckPb.CheckResult{
|
k8sClientCheck := &healthcheckPb.CheckResult{
|
||||||
SubsystemName: K8sClientSubsystemName,
|
SubsystemName: k8sClientSubsystemName,
|
||||||
CheckDescription: K8sClientCheckDescription,
|
CheckDescription: k8sClientCheckDescription,
|
||||||
Status: healthcheckPb.CheckStatus_OK,
|
Status: healthcheckPb.CheckStatus_OK,
|
||||||
}
|
}
|
||||||
_, err := s.k8sAPI.Pod().Lister().List(labels.Everything())
|
_, err := s.k8sAPI.Pod().Lister().List(labels.Everything())
|
||||||
|
@ -201,8 +201,8 @@ func (s *grpcServer) SelfCheck(ctx context.Context, in *healthcheckPb.SelfCheckR
|
||||||
}
|
}
|
||||||
|
|
||||||
promClientCheck := &healthcheckPb.CheckResult{
|
promClientCheck := &healthcheckPb.CheckResult{
|
||||||
SubsystemName: PromClientSubsystemName,
|
SubsystemName: promClientSubsystemName,
|
||||||
CheckDescription: PromClientCheckDescription,
|
CheckDescription: promClientCheckDescription,
|
||||||
Status: healthcheckPb.CheckStatus_OK,
|
Status: healthcheckPb.CheckStatus_OK,
|
||||||
}
|
}
|
||||||
_, err = s.queryProm(ctx, fmt.Sprintf(podQuery, ""))
|
_, err = s.queryProm(ctx, fmt.Sprintf(podQuery, ""))
|
||||||
|
|
|
@ -167,7 +167,7 @@ spec:
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeGrpcServer := newGrpcServer(
|
fakeGrpcServer := newGrpcServer(
|
||||||
&MockProm{Res: exp.promRes},
|
&mockProm{Res: exp.promRes},
|
||||||
tap.NewTapClient(nil),
|
tap.NewTapClient(nil),
|
||||||
k8sAPI,
|
k8sAPI,
|
||||||
"linkerd",
|
"linkerd",
|
||||||
|
@ -248,7 +248,7 @@ metadata:
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeGrpcServer := newGrpcServer(
|
fakeGrpcServer := newGrpcServer(
|
||||||
&MockProm{},
|
&mockProm{},
|
||||||
tap.NewTapClient(nil),
|
tap.NewTapClient(nil),
|
||||||
k8sAPI,
|
k8sAPI,
|
||||||
"linkerd",
|
"linkerd",
|
||||||
|
|
|
@ -239,6 +239,7 @@ func fullURLPathFor(method string) string {
|
||||||
return apiRoot + apiPrefix + method
|
return apiRoot + apiPrefix + method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewServer creates a Public API HTTP server.
|
||||||
func NewServer(
|
func NewServer(
|
||||||
addr string,
|
addr string,
|
||||||
prometheusClient promApi.Client,
|
prometheusClient promApi.Client,
|
||||||
|
|
|
@ -771,7 +771,7 @@ status:
|
||||||
|
|
||||||
for _, exp := range expectations {
|
for _, exp := range expectations {
|
||||||
fakeGrpcServer := newGrpcServer(
|
fakeGrpcServer := newGrpcServer(
|
||||||
&MockProm{Res: exp.mockPromResponse},
|
&mockProm{Res: exp.mockPromResponse},
|
||||||
tap.NewTapClient(nil),
|
tap.NewTapClient(nil),
|
||||||
k8sAPI,
|
k8sAPI,
|
||||||
"linkerd",
|
"linkerd",
|
||||||
|
@ -795,7 +795,7 @@ status:
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
fakeGrpcServer := newGrpcServer(
|
fakeGrpcServer := newGrpcServer(
|
||||||
&MockProm{Res: model.Vector{}},
|
&mockProm{Res: model.Vector{}},
|
||||||
tap.NewTapClient(nil),
|
tap.NewTapClient(nil),
|
||||||
k8sAPI,
|
k8sAPI,
|
||||||
"linkerd",
|
"linkerd",
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MockAPIClient satisfies the Public API's gRPC interface.
|
||||||
type MockAPIClient struct {
|
type MockAPIClient struct {
|
||||||
ErrorToReturn error
|
ErrorToReturn error
|
||||||
VersionInfoToReturn *pb.VersionInfo
|
VersionInfoToReturn *pb.VersionInfo
|
||||||
|
@ -30,45 +31,53 @@ type MockAPIClient struct {
|
||||||
APITapByResourceClientToReturn pb.Api_TapByResourceClient
|
APITapByResourceClientToReturn pb.Api_TapByResourceClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatSummary provides a mock of a Public API method.
|
||||||
func (c *MockAPIClient) StatSummary(ctx context.Context, in *pb.StatSummaryRequest, opts ...grpc.CallOption) (*pb.StatSummaryResponse, error) {
|
func (c *MockAPIClient) StatSummary(ctx context.Context, in *pb.StatSummaryRequest, opts ...grpc.CallOption) (*pb.StatSummaryResponse, error) {
|
||||||
return c.StatSummaryResponseToReturn, c.ErrorToReturn
|
return c.StatSummaryResponseToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TopRoutes provides a mock of a Public API method.
|
||||||
func (c *MockAPIClient) TopRoutes(ctx context.Context, in *pb.TopRoutesRequest, opts ...grpc.CallOption) (*pb.TopRoutesResponse, error) {
|
func (c *MockAPIClient) TopRoutes(ctx context.Context, in *pb.TopRoutesRequest, opts ...grpc.CallOption) (*pb.TopRoutesResponse, error) {
|
||||||
return c.TopRoutesResponseToReturn, c.ErrorToReturn
|
return c.TopRoutesResponseToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Version provides a mock of a Public API method.
|
||||||
func (c *MockAPIClient) Version(ctx context.Context, in *pb.Empty, opts ...grpc.CallOption) (*pb.VersionInfo, error) {
|
func (c *MockAPIClient) Version(ctx context.Context, in *pb.Empty, opts ...grpc.CallOption) (*pb.VersionInfo, error) {
|
||||||
return c.VersionInfoToReturn, c.ErrorToReturn
|
return c.VersionInfoToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListPods provides a mock of a Public API method.
|
||||||
func (c *MockAPIClient) ListPods(ctx context.Context, in *pb.ListPodsRequest, opts ...grpc.CallOption) (*pb.ListPodsResponse, error) {
|
func (c *MockAPIClient) ListPods(ctx context.Context, in *pb.ListPodsRequest, opts ...grpc.CallOption) (*pb.ListPodsResponse, error) {
|
||||||
return c.ListPodsResponseToReturn, c.ErrorToReturn
|
return c.ListPodsResponseToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListServices provides a mock of a Public API method.
|
||||||
func (c *MockAPIClient) ListServices(ctx context.Context, in *pb.ListServicesRequest, opts ...grpc.CallOption) (*pb.ListServicesResponse, error) {
|
func (c *MockAPIClient) ListServices(ctx context.Context, in *pb.ListServicesRequest, opts ...grpc.CallOption) (*pb.ListServicesResponse, error) {
|
||||||
return c.ListServicesResponseToReturn, c.ErrorToReturn
|
return c.ListServicesResponseToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tap provides a mock of a Public API method.
|
||||||
func (c *MockAPIClient) Tap(ctx context.Context, in *pb.TapRequest, opts ...grpc.CallOption) (pb.Api_TapClient, error) {
|
func (c *MockAPIClient) Tap(ctx context.Context, in *pb.TapRequest, opts ...grpc.CallOption) (pb.Api_TapClient, error) {
|
||||||
return c.APITapClientToReturn, c.ErrorToReturn
|
return c.APITapClientToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TapByResource provides a mock of a Public API method.
|
||||||
func (c *MockAPIClient) TapByResource(ctx context.Context, in *pb.TapByResourceRequest, opts ...grpc.CallOption) (pb.Api_TapByResourceClient, error) {
|
func (c *MockAPIClient) TapByResource(ctx context.Context, in *pb.TapByResourceRequest, opts ...grpc.CallOption) (pb.Api_TapByResourceClient, error) {
|
||||||
return c.APITapByResourceClientToReturn, c.ErrorToReturn
|
return c.APITapByResourceClientToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 *healthcheckPb.SelfCheckRequest, _ ...grpc.CallOption) (*healthcheckPb.SelfCheckResponse, error) {
|
||||||
return c.SelfCheckResponseToReturn, c.ErrorToReturn
|
return c.SelfCheckResponseToReturn, c.ErrorToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
type MockAPITapClient struct {
|
type mockAPITapClient struct {
|
||||||
TapEventsToReturn []pb.TapEvent
|
TapEventsToReturn []pb.TapEvent
|
||||||
ErrorsToReturn []error
|
ErrorsToReturn []error
|
||||||
grpc.ClientStream
|
grpc.ClientStream
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *MockAPITapClient) Recv() (*pb.TapEvent, error) {
|
func (a *mockAPITapClient) Recv() (*pb.TapEvent, error) {
|
||||||
var eventPopped pb.TapEvent
|
var eventPopped pb.TapEvent
|
||||||
var errorPopped error
|
var errorPopped error
|
||||||
if len(a.TapEventsToReturn) == 0 && len(a.ErrorsToReturn) == 0 {
|
if len(a.TapEventsToReturn) == 0 && len(a.ErrorsToReturn) == 0 {
|
||||||
|
@ -84,12 +93,14 @@ func (a *MockAPITapClient) Recv() (*pb.TapEvent, error) {
|
||||||
return &eventPopped, errorPopped
|
return &eventPopped, errorPopped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MockAPITapByResourceClient satisfies the TapByResourceClient gRPC interface.
|
||||||
type MockAPITapByResourceClient struct {
|
type MockAPITapByResourceClient struct {
|
||||||
TapEventsToReturn []pb.TapEvent
|
TapEventsToReturn []pb.TapEvent
|
||||||
ErrorsToReturn []error
|
ErrorsToReturn []error
|
||||||
grpc.ClientStream
|
grpc.ClientStream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recv satisfies the TapByResourceClient.Recv() gRPC method.
|
||||||
func (a *MockAPITapByResourceClient) Recv() (*pb.TapEvent, error) {
|
func (a *MockAPITapByResourceClient) Recv() (*pb.TapEvent, error) {
|
||||||
var eventPopped pb.TapEvent
|
var eventPopped pb.TapEvent
|
||||||
var errorPopped error
|
var errorPopped error
|
||||||
|
@ -110,37 +121,41 @@ func (a *MockAPITapByResourceClient) Recv() (*pb.TapEvent, error) {
|
||||||
// Prometheus client
|
// Prometheus client
|
||||||
//
|
//
|
||||||
|
|
||||||
type MockProm struct {
|
type mockProm struct {
|
||||||
Res model.Value
|
Res model.Value
|
||||||
QueriesExecuted []string // expose the queries our Mock Prometheus receives, to test query generation
|
QueriesExecuted []string // expose the queries our Mock Prometheus receives, to test query generation
|
||||||
rwLock sync.Mutex
|
rwLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PodCounts is a test helper struct that is used for representing data in a
|
||||||
|
// StatTable.PodGroup.Row.
|
||||||
type PodCounts struct {
|
type PodCounts struct {
|
||||||
MeshedPods uint64
|
MeshedPods uint64
|
||||||
RunningPods uint64
|
RunningPods uint64
|
||||||
FailedPods uint64
|
FailedPods uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockProm) Query(ctx context.Context, query string, ts time.Time) (model.Value, error) {
|
func (m *mockProm) Query(ctx context.Context, query string, ts time.Time) (model.Value, error) {
|
||||||
m.rwLock.Lock()
|
m.rwLock.Lock()
|
||||||
defer m.rwLock.Unlock()
|
defer m.rwLock.Unlock()
|
||||||
m.QueriesExecuted = append(m.QueriesExecuted, query)
|
m.QueriesExecuted = append(m.QueriesExecuted, query)
|
||||||
return m.Res, nil
|
return m.Res, nil
|
||||||
}
|
}
|
||||||
func (m *MockProm) QueryRange(ctx context.Context, query string, r v1.Range) (model.Value, error) {
|
func (m *mockProm) QueryRange(ctx context.Context, query string, r v1.Range) (model.Value, error) {
|
||||||
m.rwLock.Lock()
|
m.rwLock.Lock()
|
||||||
defer m.rwLock.Unlock()
|
defer m.rwLock.Unlock()
|
||||||
m.QueriesExecuted = append(m.QueriesExecuted, query)
|
m.QueriesExecuted = append(m.QueriesExecuted, query)
|
||||||
return m.Res, nil
|
return m.Res, nil
|
||||||
}
|
}
|
||||||
func (m *MockProm) LabelValues(ctx context.Context, label string) (model.LabelValues, error) {
|
func (m *mockProm) LabelValues(ctx context.Context, label string) (model.LabelValues, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
func (m *MockProm) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error) {
|
func (m *mockProm) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenStatSummaryResponse generates a mock Public API StatSummaryResponse
|
||||||
|
// object.
|
||||||
func GenStatSummaryResponse(resName, resType string, resNs []string, counts *PodCounts, basicStats bool) pb.StatSummaryResponse {
|
func GenStatSummaryResponse(resName, resType string, resNs []string, counts *PodCounts, basicStats bool) pb.StatSummaryResponse {
|
||||||
rows := []*pb.StatTable_PodGroup_Row{}
|
rows := []*pb.StatTable_PodGroup_Row{}
|
||||||
for _, ns := range resNs {
|
for _, ns := range resNs {
|
||||||
|
@ -192,6 +207,7 @@ func GenStatSummaryResponse(resName, resType string, resNs []string, counts *Pod
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenTopRoutesResponse generates a mock Public API TopRoutesResponse object.
|
||||||
func GenTopRoutesResponse(routes []string, counts []uint64) pb.TopRoutesResponse {
|
func GenTopRoutesResponse(routes []string, counts []uint64) pb.TopRoutesResponse {
|
||||||
rows := []*pb.RouteTable_Row{}
|
rows := []*pb.RouteTable_Row{}
|
||||||
for i, route := range routes {
|
for i, route := range routes {
|
||||||
|
@ -228,13 +244,13 @@ type expectedStatRPC struct {
|
||||||
expectedPrometheusQueries []string // queries we expect public-api to issue to prometheus
|
expectedPrometheusQueries []string // queries we expect public-api to issue to prometheus
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMockGrpcServer(exp expectedStatRPC) (*MockProm, *grpcServer, error) {
|
func newMockGrpcServer(exp expectedStatRPC) (*mockProm, *grpcServer, error) {
|
||||||
k8sAPI, err := k8s.NewFakeAPI("", exp.k8sConfigs...)
|
k8sAPI, err := k8s.NewFakeAPI("", exp.k8sConfigs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mockProm := &MockProm{Res: exp.mockPromResponse}
|
mockProm := &mockProm{Res: exp.mockPromResponse}
|
||||||
fakeGrpcServer := newGrpcServer(
|
fakeGrpcServer := newGrpcServer(
|
||||||
mockProm,
|
mockProm,
|
||||||
tap.NewTapClient(nil),
|
tap.NewTapClient(nil),
|
||||||
|
@ -248,7 +264,7 @@ func newMockGrpcServer(exp expectedStatRPC) (*MockProm, *grpcServer, error) {
|
||||||
return mockProm, fakeGrpcServer, nil
|
return mockProm, fakeGrpcServer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (exp expectedStatRPC) verifyPromQueries(mockProm *MockProm) error {
|
func (exp expectedStatRPC) verifyPromQueries(mockProm *mockProm) error {
|
||||||
// if exp.expectedPrometheusQueries is an empty slice we still wanna check no queries were executed.
|
// if exp.expectedPrometheusQueries is an empty slice we still wanna check no queries were executed.
|
||||||
if exp.expectedPrometheusQueries != nil {
|
if exp.expectedPrometheusQueries != nil {
|
||||||
sort.Strings(exp.expectedPrometheusQueries)
|
sort.Strings(exp.expectedPrometheusQueries)
|
||||||
|
|
|
@ -49,7 +49,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// StatsBaseRequestParams contains parameters that are used to build requests
|
// StatsBaseRequestParams contains parameters that are used to build requests
|
||||||
// for metrics data. This includes requests to StatSummary and TopRoutes
|
// for metrics data. This includes requests to StatSummary and TopRoutes.
|
||||||
type StatsBaseRequestParams struct {
|
type StatsBaseRequestParams struct {
|
||||||
TimeWindow string
|
TimeWindow string
|
||||||
Namespace string
|
Namespace string
|
||||||
|
@ -58,6 +58,8 @@ type StatsBaseRequestParams struct {
|
||||||
AllNamespaces bool
|
AllNamespaces bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatsSummaryRequestParams contains parameters that are used to build
|
||||||
|
// StatSummary requests.
|
||||||
type StatsSummaryRequestParams struct {
|
type StatsSummaryRequestParams struct {
|
||||||
StatsBaseRequestParams
|
StatsBaseRequestParams
|
||||||
ToNamespace string
|
ToNamespace string
|
||||||
|
@ -69,12 +71,16 @@ type StatsSummaryRequestParams struct {
|
||||||
SkipStats bool
|
SkipStats bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TopRoutesRequestParams contains parameters that are used to build TopRoutes
|
||||||
|
// requests.
|
||||||
type TopRoutesRequestParams struct {
|
type TopRoutesRequestParams struct {
|
||||||
StatsBaseRequestParams
|
StatsBaseRequestParams
|
||||||
To string
|
To string
|
||||||
ToAll bool
|
ToAll bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TapRequestParams contains parameters that are used to build a
|
||||||
|
// TapByResourceRequest.
|
||||||
type TapRequestParams struct {
|
type TapRequestParams struct {
|
||||||
Resource string
|
Resource string
|
||||||
Namespace string
|
Namespace string
|
||||||
|
@ -119,6 +125,8 @@ func GRPCError(err error) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuildStatSummaryRequest builds a Public API StatSummaryRequest from a
|
||||||
|
// StatsSummaryRequestParams.
|
||||||
func BuildStatSummaryRequest(p StatsSummaryRequestParams) (*pb.StatSummaryRequest, error) {
|
func BuildStatSummaryRequest(p StatsSummaryRequestParams) (*pb.StatSummaryRequest, error) {
|
||||||
window := defaultMetricTimeWindow
|
window := defaultMetricTimeWindow
|
||||||
if p.TimeWindow != "" {
|
if p.TimeWindow != "" {
|
||||||
|
@ -206,6 +214,8 @@ func BuildStatSummaryRequest(p StatsSummaryRequestParams) (*pb.StatSummaryReques
|
||||||
return statRequest, nil
|
return statRequest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuildTopRoutesRequest builds a Public API TopRoutesRequest from a
|
||||||
|
// TopRoutesRequestParams.
|
||||||
func BuildTopRoutesRequest(p TopRoutesRequestParams) (*pb.TopRoutesRequest, error) {
|
func BuildTopRoutesRequest(p TopRoutesRequestParams) (*pb.TopRoutesRequest, error) {
|
||||||
window := defaultMetricTimeWindow
|
window := defaultMetricTimeWindow
|
||||||
if p.TimeWindow != "" {
|
if p.TimeWindow != "" {
|
||||||
|
@ -372,6 +382,8 @@ func buildResource(namespace string, resType string, name string) (pb.Resource,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuildTapByResourceRequest builds a Public API TapByResourceRequest from a
|
||||||
|
// TapRequestParams.
|
||||||
func BuildTapByResourceRequest(params TapRequestParams) (*pb.TapByResourceRequest, error) {
|
func BuildTapByResourceRequest(params TapRequestParams) (*pb.TapByResourceRequest, error) {
|
||||||
target, err := BuildResource(params.Namespace, params.Resource)
|
target, err := BuildResource(params.Namespace, params.Resource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -535,6 +547,8 @@ func routeLabels(event *pb.TapEvent) string {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderTapEvent renders a Public API TapEvent to a string.
|
||||||
|
// TODO: consider moving this into cli/cmd/tap.go.
|
||||||
func RenderTapEvent(event *pb.TapEvent, resource string) string {
|
func RenderTapEvent(event *pb.TapEvent, resource string) string {
|
||||||
dst := dst(event)
|
dst := dst(event)
|
||||||
src := src(event)
|
src := src(event)
|
||||||
|
@ -634,6 +648,8 @@ func RenderTapEvent(event *pb.TapEvent, resource string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRequestRate calculates request rate from Public API BasicStats.
|
||||||
|
// TODO: consider moving this into `/cli/cmd`.
|
||||||
func GetRequestRate(stats *pb.BasicStats, timeWindow string) float64 {
|
func GetRequestRate(stats *pb.BasicStats, timeWindow string) float64 {
|
||||||
success := stats.SuccessCount
|
success := stats.SuccessCount
|
||||||
failure := stats.FailureCount
|
failure := stats.FailureCount
|
||||||
|
@ -645,6 +661,8 @@ func GetRequestRate(stats *pb.BasicStats, timeWindow string) float64 {
|
||||||
return float64(success+failure) / windowLength.Seconds()
|
return float64(success+failure) / windowLength.Seconds()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSuccessRate calculates success rate from Public API BasicStats.
|
||||||
|
// TODO: consider moving this into `/cli/cmd`.
|
||||||
func GetSuccessRate(stats *pb.BasicStats) float64 {
|
func GetSuccessRate(stats *pb.BasicStats) float64 {
|
||||||
success := stats.SuccessCount
|
success := stats.SuccessCount
|
||||||
failure := stats.FailureCount
|
failure := stats.FailureCount
|
||||||
|
@ -655,6 +673,9 @@ func GetSuccessRate(stats *pb.BasicStats) float64 {
|
||||||
return float64(success) / float64(success+failure)
|
return float64(success) / float64(success+failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPercentTLS calculates the percent of traffic that is TLS, from Public API
|
||||||
|
// BasicStats.
|
||||||
|
// TODO: consider moving this into `/cli/cmd/stat.go`.
|
||||||
func GetPercentTLS(stats *pb.BasicStats) float64 {
|
func GetPercentTLS(stats *pb.BasicStats) float64 {
|
||||||
reqTotal := stats.SuccessCount + stats.FailureCount
|
reqTotal := stats.SuccessCount + stats.FailureCount
|
||||||
if reqTotal == 0 {
|
if reqTotal == 0 {
|
||||||
|
|
|
@ -48,6 +48,7 @@ type CA struct {
|
||||||
nextSerialNumber uint64
|
nextSerialNumber uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CertificateAndPrivateKey encapsulates a certificate / private key pair.
|
||||||
type CertificateAndPrivateKey struct {
|
type CertificateAndPrivateKey struct {
|
||||||
// The ASN.1 DER-encoded (binary, not PEM) certificate.
|
// The ASN.1 DER-encoded (binary, not PEM) certificate.
|
||||||
Certificate []byte
|
Certificate []byte
|
||||||
|
|
|
@ -18,6 +18,8 @@ import (
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CertificateController listens for added and updated meshed pods, and then
|
||||||
|
// provides certificates in the form of secrets.
|
||||||
type CertificateController struct {
|
type CertificateController struct {
|
||||||
namespace string
|
namespace string
|
||||||
k8sAPI *k8s.API
|
k8sAPI *k8s.API
|
||||||
|
@ -32,6 +34,8 @@ type CertificateController struct {
|
||||||
queue workqueue.RateLimitingInterface
|
queue workqueue.RateLimitingInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewCertificateController initializes a CertificateController and its
|
||||||
|
// internal Certificate Authority.
|
||||||
func NewCertificateController(controllerNamespace string, k8sAPI *k8s.API, proxyAutoInject bool) (*CertificateController, error) {
|
func NewCertificateController(controllerNamespace string, k8sAPI *k8s.API, proxyAutoInject bool) (*CertificateController, error) {
|
||||||
ca, err := NewCA()
|
ca, err := NewCA()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -67,6 +71,7 @@ func NewCertificateController(controllerNamespace string, k8sAPI *k8s.API, proxy
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run kicks off CertificateController queue processing.
|
||||||
func (c *CertificateController) Run(stopCh <-chan struct{}) {
|
func (c *CertificateController) Run(stopCh <-chan struct{}) {
|
||||||
defer runtime.HandleCrash()
|
defer runtime.HandleCrash()
|
||||||
defer c.queue.ShutDown()
|
defer c.queue.ShutDown()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
package serviceprofile
|
package serviceprofile
|
||||||
|
|
||||||
|
// GroupName identifies the API Group Name for a ServiceProfile.
|
||||||
const GroupName = "linkerd.io"
|
const GroupName = "linkerd.io"
|
||||||
|
|
|
@ -26,8 +26,15 @@ func Resource(resource string) schema.GroupResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// SchemeBuilder collects functions that add things to a scheme. It's to allow
|
||||||
|
// code to compile without explicitly referencing generated types. You should
|
||||||
|
// declare one in each package that will have generated deep copy or conversion
|
||||||
|
// functions.
|
||||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||||
AddToScheme = SchemeBuilder.AddToScheme
|
|
||||||
|
// AddToScheme applies all the stored functions to the scheme. A non-nil error
|
||||||
|
// indicates that one function failed and the attempt was abandoned.
|
||||||
|
AddToScheme = SchemeBuilder.AddToScheme
|
||||||
)
|
)
|
||||||
|
|
||||||
// Adds the list of known types to Scheme.
|
// Adds the list of known types to Scheme.
|
||||||
|
|
|
@ -25,16 +25,19 @@ type ServiceProfile struct {
|
||||||
Spec ServiceProfileSpec `json:"spec"`
|
Spec ServiceProfileSpec `json:"spec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServiceProfileSpec specifies a ServiceProfile resource.
|
||||||
type ServiceProfileSpec struct {
|
type ServiceProfileSpec struct {
|
||||||
Routes []*RouteSpec `json:"routes"`
|
Routes []*RouteSpec `json:"routes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RouteSpec specifies a Route resource.
|
||||||
type RouteSpec struct {
|
type RouteSpec struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Condition *RequestMatch `json:"condition"`
|
Condition *RequestMatch `json:"condition"`
|
||||||
ResponseClasses []*ResponseClass `json:"responseClasses,omitempty"`
|
ResponseClasses []*ResponseClass `json:"responseClasses,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequestMatch describes the conditions under which to match a Route.
|
||||||
type RequestMatch struct {
|
type RequestMatch struct {
|
||||||
All []*RequestMatch `json:"all,omitempty"`
|
All []*RequestMatch `json:"all,omitempty"`
|
||||||
Not *RequestMatch `json:"not,omitempty"`
|
Not *RequestMatch `json:"not,omitempty"`
|
||||||
|
@ -43,11 +46,14 @@ type RequestMatch struct {
|
||||||
Method string `json:"method,omitempty"`
|
Method string `json:"method,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResponseClass describes how to classify a response (e.g. success or
|
||||||
|
// failures).
|
||||||
type ResponseClass struct {
|
type ResponseClass struct {
|
||||||
Condition *ResponseMatch `json:"condition"`
|
Condition *ResponseMatch `json:"condition"`
|
||||||
IsFailure bool `json:"isFailure,omitempty"`
|
IsFailure bool `json:"isFailure,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResponseMatch describes the conditions under which to classify a response.
|
||||||
type ResponseMatch struct {
|
type ResponseMatch struct {
|
||||||
All []*ResponseMatch `json:"all,omitempty"`
|
All []*ResponseMatch `json:"all,omitempty"`
|
||||||
Not *ResponseMatch `json:"not,omitempty"`
|
Not *ResponseMatch `json:"not,omitempty"`
|
||||||
|
@ -55,6 +61,7 @@ type ResponseMatch struct {
|
||||||
Status *Range `json:"status,omitempty"`
|
Status *Range `json:"status,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Range describes a range of integers (e.g. status codes).
|
||||||
type Range struct {
|
type Range struct {
|
||||||
Min uint32 `json:"min,omitempty"`
|
Min uint32 `json:"min,omitempty"`
|
||||||
Max uint32 `json:"max,omitempty"`
|
Max uint32 `json:"max,omitempty"`
|
||||||
|
@ -62,7 +69,7 @@ type Range struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
// ServiceProfileList is a list of ServiceProfile resources
|
// ServiceProfileList is a list of ServiceProfile resources.
|
||||||
type ServiceProfileList struct {
|
type ServiceProfileList struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ListMeta `json:"metadata"`
|
metav1.ListMeta `json:"metadata"`
|
||||||
|
|
|
@ -26,8 +26,11 @@ import (
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// APIResource is an enum for Kubernetes API resource types, for use when
|
||||||
|
// initializing a K8s API, to describe which resource types to interact with.
|
||||||
type APIResource int
|
type APIResource int
|
||||||
|
|
||||||
|
// These constants enumerate Kubernetes resource types.
|
||||||
const (
|
const (
|
||||||
CM APIResource = iota
|
CM APIResource = iota
|
||||||
Deploy
|
Deploy
|
||||||
|
@ -140,6 +143,7 @@ func (api *API) Sync() {
|
||||||
log.Infof("caches synced")
|
log.Infof("caches synced")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deploy provides access to a shared informer and lister for Deployments.
|
||||||
func (api *API) Deploy() appinformers.DeploymentInformer {
|
func (api *API) Deploy() appinformers.DeploymentInformer {
|
||||||
if api.deploy == nil {
|
if api.deploy == nil {
|
||||||
panic("Deploy informer not configured")
|
panic("Deploy informer not configured")
|
||||||
|
@ -147,6 +151,7 @@ func (api *API) Deploy() appinformers.DeploymentInformer {
|
||||||
return api.deploy
|
return api.deploy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RS provides access to a shared informer and lister for ReplicaSets.
|
||||||
func (api *API) RS() appinformers.ReplicaSetInformer {
|
func (api *API) RS() appinformers.ReplicaSetInformer {
|
||||||
if api.rs == nil {
|
if api.rs == nil {
|
||||||
panic("RS informer not configured")
|
panic("RS informer not configured")
|
||||||
|
@ -154,6 +159,7 @@ func (api *API) RS() appinformers.ReplicaSetInformer {
|
||||||
return api.rs
|
return api.rs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pod provides access to a shared informer and lister for Pods.
|
||||||
func (api *API) Pod() coreinformers.PodInformer {
|
func (api *API) Pod() coreinformers.PodInformer {
|
||||||
if api.pod == nil {
|
if api.pod == nil {
|
||||||
panic("Pod informer not configured")
|
panic("Pod informer not configured")
|
||||||
|
@ -161,6 +167,8 @@ func (api *API) Pod() coreinformers.PodInformer {
|
||||||
return api.pod
|
return api.pod
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RC provides access to a shared informer and lister for
|
||||||
|
// ReplicationControllers.
|
||||||
func (api *API) RC() coreinformers.ReplicationControllerInformer {
|
func (api *API) RC() coreinformers.ReplicationControllerInformer {
|
||||||
if api.rc == nil {
|
if api.rc == nil {
|
||||||
panic("RC informer not configured")
|
panic("RC informer not configured")
|
||||||
|
@ -168,6 +176,7 @@ func (api *API) RC() coreinformers.ReplicationControllerInformer {
|
||||||
return api.rc
|
return api.rc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Svc provides access to a shared informer and lister for Services.
|
||||||
func (api *API) Svc() coreinformers.ServiceInformer {
|
func (api *API) Svc() coreinformers.ServiceInformer {
|
||||||
if api.svc == nil {
|
if api.svc == nil {
|
||||||
panic("Svc informer not configured")
|
panic("Svc informer not configured")
|
||||||
|
@ -175,6 +184,7 @@ func (api *API) Svc() coreinformers.ServiceInformer {
|
||||||
return api.svc
|
return api.svc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Endpoint provides access to a shared informer and lister for Endpoints.
|
||||||
func (api *API) Endpoint() coreinformers.EndpointsInformer {
|
func (api *API) Endpoint() coreinformers.EndpointsInformer {
|
||||||
if api.endpoint == nil {
|
if api.endpoint == nil {
|
||||||
panic("Endpoint informer not configured")
|
panic("Endpoint informer not configured")
|
||||||
|
@ -182,6 +192,7 @@ func (api *API) Endpoint() coreinformers.EndpointsInformer {
|
||||||
return api.endpoint
|
return api.endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CM provides access to a shared informer and lister for ConfigMaps.
|
||||||
func (api *API) CM() coreinformers.ConfigMapInformer {
|
func (api *API) CM() coreinformers.ConfigMapInformer {
|
||||||
if api.cm == nil {
|
if api.cm == nil {
|
||||||
panic("CM informer not configured")
|
panic("CM informer not configured")
|
||||||
|
@ -189,6 +200,7 @@ func (api *API) CM() coreinformers.ConfigMapInformer {
|
||||||
return api.cm
|
return api.cm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SP provides access to a shared informer and lister for ServiceProfiles.
|
||||||
func (api *API) SP() spinformers.ServiceProfileInformer {
|
func (api *API) SP() spinformers.ServiceProfileInformer {
|
||||||
if api.sp == nil {
|
if api.sp == nil {
|
||||||
panic("SP informer not configured")
|
panic("SP informer not configured")
|
||||||
|
@ -196,6 +208,7 @@ func (api *API) SP() spinformers.ServiceProfileInformer {
|
||||||
return api.sp
|
return api.sp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MWC provides access to a shared informer and lister for MutatingWebhookConfigurations.
|
||||||
func (api *API) MWC() arinformers.MutatingWebhookConfigurationInformer {
|
func (api *API) MWC() arinformers.MutatingWebhookConfigurationInformer {
|
||||||
if api.mwc == nil {
|
if api.mwc == nil {
|
||||||
panic("MWC informer not configured")
|
panic("MWC informer not configured")
|
||||||
|
@ -439,6 +452,8 @@ func (api *API) getServices(namespace, name string) ([]runtime.Object, error) {
|
||||||
return objects, nil
|
return objects, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetServices returns a list of Service resources, based on input namespace and
|
||||||
|
// name.
|
||||||
func (api *API) GetServices(namespace, name string) ([]*apiv1.Service, error) {
|
func (api *API) GetServices(namespace, name string) ([]*apiv1.Service, error) {
|
||||||
var err error
|
var err error
|
||||||
var services []*apiv1.Service
|
var services []*apiv1.Service
|
||||||
|
|
|
@ -4,10 +4,12 @@ import (
|
||||||
spclient "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
|
spclient "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
|
||||||
"github.com/linkerd/linkerd2/pkg/k8s"
|
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
// Load all the auth plugins for the cloud providers.
|
// Load all the auth plugins for the cloud providers.
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewClientSet returns a Kubernetes client for the given configuration.
|
||||||
func NewClientSet(kubeConfig string) (*kubernetes.Clientset, error) {
|
func NewClientSet(kubeConfig string) (*kubernetes.Clientset, error) {
|
||||||
config, err := k8s.GetConfig(kubeConfig, "")
|
config, err := k8s.GetConfig(kubeConfig, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -17,6 +19,8 @@ func NewClientSet(kubeConfig string) (*kubernetes.Clientset, error) {
|
||||||
return kubernetes.NewForConfig(config)
|
return kubernetes.NewForConfig(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSpClientSet returns a Kubernetes ServiceProfile client for the given
|
||||||
|
// configuration.
|
||||||
func NewSpClientSet(kubeConfig string) (*spclient.Clientset, error) {
|
func NewSpClientSet(kubeConfig string) (*spclient.Clientset, error) {
|
||||||
config, err := k8s.GetConfig(kubeConfig, "")
|
config, err := k8s.GetConfig(kubeConfig, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -18,6 +18,7 @@ func toRuntimeObject(config string) (runtime.Object, error) {
|
||||||
return obj, err
|
return obj, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFakeAPI provides a mock Kubernetes API for testing.
|
||||||
func NewFakeAPI(namespace string, configs ...string) (*API, error) {
|
func NewFakeAPI(namespace string, configs ...string) (*API, error) {
|
||||||
objs := []runtime.Object{}
|
objs := []runtime.Object{}
|
||||||
spObjs := []runtime.Object{}
|
spObjs := []runtime.Object{}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// These constants provide default, fake strings for testing proxy-injector.
|
||||||
const (
|
const (
|
||||||
DefaultControllerNamespace = "linkerd"
|
DefaultControllerNamespace = "linkerd"
|
||||||
DefaultNamespace = "default"
|
DefaultNamespace = "default"
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package tmpl
|
package tmpl
|
||||||
|
|
||||||
|
// MutatingWebhookConfigurationSpec provides a template for a
|
||||||
|
// MutatingWebhookConfiguration.
|
||||||
var MutatingWebhookConfigurationSpec = `
|
var MutatingWebhookConfigurationSpec = `
|
||||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||||
kind: MutatingWebhookConfiguration
|
kind: MutatingWebhookConfiguration
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewClient creates a client for the control-plane's Tap service.
|
||||||
func NewClient(addr string) (pb.TapClient, *grpc.ClientConn, error) {
|
func NewClient(addr string) (pb.TapClient, *grpc.ClientConn, error) {
|
||||||
conn, err := grpc.Dial(addr, grpc.WithInsecure())
|
conn, err := grpc.Dial(addr, grpc.WithInsecure())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,21 +9,25 @@ import (
|
||||||
"github.com/linkerd/linkerd2/controller/gen/public"
|
"github.com/linkerd/linkerd2/controller/gen/public"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PublicAddressToString formats a Public API TCPAddress as a string.
|
||||||
func PublicAddressToString(addr *public.TcpAddress) string {
|
func PublicAddressToString(addr *public.TcpAddress) string {
|
||||||
octects := decodeIPToOctets(addr.GetIp().GetIpv4())
|
octects := decodeIPToOctets(addr.GetIp().GetIpv4())
|
||||||
return fmt.Sprintf("%d.%d.%d.%d:%d", octects[0], octects[1], octects[2], octects[3], addr.GetPort())
|
return fmt.Sprintf("%d.%d.%d.%d:%d", octects[0], octects[1], octects[2], octects[3], addr.GetPort())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PublicIPToString formats a Public API IPAddress as a string.
|
||||||
func PublicIPToString(ip *public.IPAddress) string {
|
func PublicIPToString(ip *public.IPAddress) string {
|
||||||
octets := decodeIPToOctets(ip.GetIpv4())
|
octets := decodeIPToOctets(ip.GetIpv4())
|
||||||
return fmt.Sprintf("%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3])
|
return fmt.Sprintf("%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyAddressToString formats a Proxy API TCPAddress as a string.
|
||||||
func ProxyAddressToString(addr *pb.TcpAddress) string {
|
func ProxyAddressToString(addr *pb.TcpAddress) string {
|
||||||
octects := decodeIPToOctets(addr.GetIp().GetIpv4())
|
octects := decodeIPToOctets(addr.GetIp().GetIpv4())
|
||||||
return fmt.Sprintf("%d.%d.%d.%d:%d", octects[0], octects[1], octects[2], octects[3], addr.GetPort())
|
return fmt.Sprintf("%d.%d.%d.%d:%d", octects[0], octects[1], octects[2], octects[3], addr.GetPort())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyAddressesToString formats a list of Proxy API TCPAddresses as a string.
|
||||||
func ProxyAddressesToString(addrs []pb.TcpAddress) string {
|
func ProxyAddressesToString(addrs []pb.TcpAddress) string {
|
||||||
addrStrs := make([]string, len(addrs))
|
addrStrs := make([]string, len(addrs))
|
||||||
for i := range addrs {
|
for i := range addrs {
|
||||||
|
@ -32,11 +36,13 @@ func ProxyAddressesToString(addrs []pb.TcpAddress) string {
|
||||||
return "[" + strings.Join(addrStrs, ",") + "]"
|
return "[" + strings.Join(addrStrs, ",") + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyIPToString formats a Proxy API IPAddress as a string.
|
||||||
func ProxyIPToString(ip *pb.IPAddress) string {
|
func ProxyIPToString(ip *pb.IPAddress) string {
|
||||||
octets := decodeIPToOctets(ip.GetIpv4())
|
octets := decodeIPToOctets(ip.GetIpv4())
|
||||||
return fmt.Sprintf("%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3])
|
return fmt.Sprintf("%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyIPV4 encodes 4 octets as a Proxy API IPAddress.
|
||||||
func ProxyIPV4(a1, a2, a3, a4 uint8) *pb.IPAddress {
|
func ProxyIPV4(a1, a2, a3, a4 uint8) *pb.IPAddress {
|
||||||
ip := (uint32(a1) << 24) | (uint32(a2) << 16) | (uint32(a3) << 8) | uint32(a4)
|
ip := (uint32(a1) << 24) | (uint32(a2) << 16) | (uint32(a3) << 8) | uint32(a4)
|
||||||
return &pb.IPAddress{
|
return &pb.IPAddress{
|
||||||
|
@ -46,6 +52,7 @@ func ProxyIPV4(a1, a2, a3, a4 uint8) *pb.IPAddress {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseProxyIPV4 parses an IP Address string into a Proxy API IPAddress.
|
||||||
func ParseProxyIPV4(ip string) (*pb.IPAddress, error) {
|
func ParseProxyIPV4(ip string) (*pb.IPAddress, error) {
|
||||||
segments := strings.Split(ip, ".")
|
segments := strings.Split(ip, ".")
|
||||||
if len(segments) != 4 {
|
if len(segments) != 4 {
|
||||||
|
@ -62,6 +69,7 @@ func ParseProxyIPV4(ip string) (*pb.IPAddress, error) {
|
||||||
return ProxyIPV4(octets[0], octets[1], octets[2], octets[3]), nil
|
return ProxyIPV4(octets[0], octets[1], octets[2], octets[3]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PublicIPV4 encodes 4 octets as a Public API IPAddress.
|
||||||
func PublicIPV4(a1, a2, a3, a4 uint8) *public.IPAddress {
|
func PublicIPV4(a1, a2, a3, a4 uint8) *public.IPAddress {
|
||||||
ip := (uint32(a1) << 24) | (uint32(a2) << 16) | (uint32(a3) << 8) | uint32(a4)
|
ip := (uint32(a1) << 24) | (uint32(a2) << 16) | (uint32(a3) << 8) | uint32(a4)
|
||||||
return &public.IPAddress{
|
return &public.IPAddress{
|
||||||
|
@ -71,6 +79,7 @@ func PublicIPV4(a1, a2, a3, a4 uint8) *public.IPAddress {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParsePublicIPV4 parses an IP Address string into a Public API IPAddress.
|
||||||
func ParsePublicIPV4(ip string) (*public.IPAddress, error) {
|
func ParsePublicIPV4(ip string) (*public.IPAddress, error) {
|
||||||
segments := strings.Split(ip, ".")
|
segments := strings.Split(ip, ".")
|
||||||
if len(segments) != 4 {
|
if len(segments) != 4 {
|
||||||
|
|
|
@ -12,6 +12,7 @@ type handler struct {
|
||||||
promHandler http.Handler
|
promHandler http.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartServer starts an admin server listening on a given address.
|
||||||
func StartServer(addr string) {
|
func StartServer(addr string) {
|
||||||
log.Infof("starting admin server on %s", addr)
|
log.Infof("starting admin server on %s", addr)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FileSystem provides access to a collection of named files via
|
||||||
|
// http.FileSystem, given a directory.
|
||||||
func FileSystem(dir string) http.FileSystem {
|
func FileSystem(dir string) http.FileSystem {
|
||||||
return fileSystem{http.Dir(dir)}
|
return fileSystem{http.Dir(dir)}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Checks is an enum for the types of health checks.
|
||||||
type Checks int
|
type Checks int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -56,11 +57,19 @@ const (
|
||||||
// and ShouldCheckDataPlaneVersion options are false.
|
// and ShouldCheckDataPlaneVersion options are false.
|
||||||
LinkerdVersionChecks
|
LinkerdVersionChecks
|
||||||
|
|
||||||
KubernetesAPICategory = "kubernetes-api"
|
// KubernetesAPICategory is the string representation of KubernetesAPIChecks.
|
||||||
|
KubernetesAPICategory = "kubernetes-api"
|
||||||
|
// LinkerdPreInstallCategory is the string representation of
|
||||||
|
// LinkerdPreInstallChecks.
|
||||||
LinkerdPreInstallCategory = "kubernetes-setup"
|
LinkerdPreInstallCategory = "kubernetes-setup"
|
||||||
LinkerdDataPlaneCategory = "linkerd-data-plane"
|
// LinkerdDataPlaneCategory is the string representation of
|
||||||
LinkerdAPICategory = "linkerd-api"
|
// LinkerdDataPlaneChecks.
|
||||||
LinkerdVersionCategory = "linkerd-version"
|
LinkerdDataPlaneCategory = "linkerd-data-plane"
|
||||||
|
// LinkerdAPICategory is the string representation of LinkerdAPIChecks.
|
||||||
|
LinkerdAPICategory = "linkerd-api"
|
||||||
|
// LinkerdVersionCategory is the string representation of
|
||||||
|
// LinkerdVersionChecks.
|
||||||
|
LinkerdVersionCategory = "linkerd-version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -100,6 +109,7 @@ type checker struct {
|
||||||
checkRPC func() (*healthcheckPb.SelfCheckResponse, error)
|
checkRPC func() (*healthcheckPb.SelfCheckResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckResult encapsulates a check's identifying information and output
|
||||||
type CheckResult struct {
|
type CheckResult struct {
|
||||||
Category string
|
Category string
|
||||||
Description string
|
Description string
|
||||||
|
@ -110,6 +120,7 @@ type CheckResult struct {
|
||||||
|
|
||||||
type checkObserver func(*CheckResult)
|
type checkObserver func(*CheckResult)
|
||||||
|
|
||||||
|
// Options specifies configuration for a HealthChecker.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
ControlPlaneNamespace string
|
ControlPlaneNamespace string
|
||||||
DataPlaneNamespace string
|
DataPlaneNamespace string
|
||||||
|
@ -124,6 +135,8 @@ type Options struct {
|
||||||
SingleNamespace bool
|
SingleNamespace bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HealthChecker encapsulates all health check checkers, and clients required to
|
||||||
|
// perform those checks.
|
||||||
type HealthChecker struct {
|
type HealthChecker struct {
|
||||||
checkers []*checker
|
checkers []*checker
|
||||||
*Options
|
*Options
|
||||||
|
@ -139,6 +152,7 @@ type HealthChecker struct {
|
||||||
latestVersion string
|
latestVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewHealthChecker returns an initialized HealthChecker
|
||||||
func NewHealthChecker(checks []Checks, options *Options) *HealthChecker {
|
func NewHealthChecker(checks []Checks, options *Options) *HealthChecker {
|
||||||
hc := &HealthChecker{
|
hc := &HealthChecker{
|
||||||
checkers: make([]*checker, 0),
|
checkers: make([]*checker, 0),
|
||||||
|
|
|
@ -19,10 +19,13 @@ import (
|
||||||
|
|
||||||
var minAPIVersion = [3]int{1, 8, 0}
|
var minAPIVersion = [3]int{1, 8, 0}
|
||||||
|
|
||||||
|
// KubernetesAPI provides a client for accessing a Kubernetes cluster.
|
||||||
type KubernetesAPI struct {
|
type KubernetesAPI struct {
|
||||||
*rest.Config
|
*rest.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewClient returns an http.Client configured with a Transport to connect to
|
||||||
|
// the Kubernetes cluster.
|
||||||
func (kubeAPI *KubernetesAPI) NewClient() (*http.Client, error) {
|
func (kubeAPI *KubernetesAPI) NewClient() (*http.Client, error) {
|
||||||
secureTransport, err := rest.TransportFor(kubeAPI.Config)
|
secureTransport, err := rest.TransportFor(kubeAPI.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -34,6 +37,7 @@ func (kubeAPI *KubernetesAPI) NewClient() (*http.Client, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetVersionInfo returns version.Info for the Kubernetes cluster.
|
||||||
func (kubeAPI *KubernetesAPI) GetVersionInfo(client *http.Client) (*version.Info, error) {
|
func (kubeAPI *KubernetesAPI) GetVersionInfo(client *http.Client) (*version.Info, error) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -58,6 +62,8 @@ func (kubeAPI *KubernetesAPI) GetVersionInfo(client *http.Client) (*version.Info
|
||||||
return &versionInfo, err
|
return &versionInfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckVersion validates whether the configured Kubernetes cluster's version is
|
||||||
|
// running a minimum Kubernetes API version.
|
||||||
func (kubeAPI *KubernetesAPI) CheckVersion(versionInfo *version.Info) error {
|
func (kubeAPI *KubernetesAPI) CheckVersion(versionInfo *version.Info) error {
|
||||||
apiVersion, err := getK8sVersion(versionInfo.String())
|
apiVersion, err := getK8sVersion(versionInfo.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -73,6 +79,7 @@ func (kubeAPI *KubernetesAPI) CheckVersion(versionInfo *version.Info) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NamespaceExists validates whether a given namespace exists.
|
||||||
func (kubeAPI *KubernetesAPI) NamespaceExists(client *http.Client, namespace string) (bool, error) {
|
func (kubeAPI *KubernetesAPI) NamespaceExists(client *http.Client, namespace string) (bool, error) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// These constants are string representations of Kubernetes resource types.
|
||||||
const (
|
const (
|
||||||
All = "all"
|
All = "all"
|
||||||
Authority = "authority"
|
Authority = "authority"
|
||||||
|
@ -159,6 +160,10 @@ func ShortNameFromCanonicalResourceName(canonicalName string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KindToL5DLabel converts a Kubernetes `kind` to a Linkerd label.
|
||||||
|
// For example:
|
||||||
|
// `pod` -> `pod`
|
||||||
|
// `job` -> `k8s_job`
|
||||||
func KindToL5DLabel(k8sKind string) string {
|
func KindToL5DLabel(k8sKind string) string {
|
||||||
if k8sKind == Job {
|
if k8sKind == Job {
|
||||||
return l5dJob
|
return l5dJob
|
||||||
|
|
|
@ -120,7 +120,12 @@ const (
|
||||||
// that contains the actual trust anchor bundle.
|
// that contains the actual trust anchor bundle.
|
||||||
TLSTrustAnchorFileName = "trust-anchors.pem"
|
TLSTrustAnchorFileName = "trust-anchors.pem"
|
||||||
|
|
||||||
TLSCertFileName = "certificate.crt"
|
// TLSCertFileName is the name (key) within proxy-injector ConfigMap that
|
||||||
|
// contains the TLS certificate.
|
||||||
|
TLSCertFileName = "certificate.crt"
|
||||||
|
|
||||||
|
// TLSPrivateKeyFileName is the name (key) within proxy-injector ConfigMap
|
||||||
|
// that contains the TLS private key.
|
||||||
TLSPrivateKeyFileName = "private-key.p8"
|
TLSPrivateKeyFileName = "private-key.p8"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -185,6 +190,7 @@ func GetPodLabels(ownerKind, ownerName string, pod *coreV1.Pod) map[string]strin
|
||||||
return labels
|
return labels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMeshed returns whether a given Pod is in a given controller's service mesh.
|
||||||
func IsMeshed(pod *coreV1.Pod, controllerNS string) bool {
|
func IsMeshed(pod *coreV1.Pod, controllerNS string) bool {
|
||||||
return pod.Labels[ControllerNSLabel] == controllerNS
|
return pod.Labels[ControllerNSLabel] == controllerNS
|
||||||
}
|
}
|
||||||
|
@ -207,6 +213,7 @@ type TLSIdentity struct {
|
||||||
ControllerNamespace string
|
ControllerNamespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToDNSName formats a TLSIdentity as a DNS name.
|
||||||
func (i TLSIdentity) ToDNSName() string {
|
func (i TLSIdentity) ToDNSName() string {
|
||||||
if i.Kind == Service {
|
if i.Kind == Service {
|
||||||
return fmt.Sprintf("%s.%s.svc", i.Name, i.Namespace)
|
return fmt.Sprintf("%s.%s.svc", i.Name, i.Namespace)
|
||||||
|
@ -215,10 +222,13 @@ func (i TLSIdentity) ToDNSName() string {
|
||||||
i.Kind, i.Namespace, i.ControllerNamespace)
|
i.Kind, i.Namespace, i.ControllerNamespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToSecretName formats a TLSIdentity as a secret name.
|
||||||
func (i TLSIdentity) ToSecretName() string {
|
func (i TLSIdentity) ToSecretName() string {
|
||||||
return fmt.Sprintf("%s-%s-tls-linkerd-io", i.Name, i.Kind)
|
return fmt.Sprintf("%s-%s-tls-linkerd-io", i.Name, i.Kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToControllerIdentity returns the TLSIdentity of the Linkerd Controller, given
|
||||||
|
// an arbitrary TLSIdentity.
|
||||||
func (i TLSIdentity) ToControllerIdentity() TLSIdentity {
|
func (i TLSIdentity) ToControllerIdentity() TLSIdentity {
|
||||||
return TLSIdentity{
|
return TLSIdentity{
|
||||||
Name: "controller",
|
Name: "controller",
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// KubernetesProxy provides a proxied connection into a Kubernetes cluster.
|
||||||
type KubernetesProxy struct {
|
type KubernetesProxy struct {
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
server *proxy.Server
|
server *proxy.Server
|
||||||
|
|
|
@ -18,6 +18,7 @@ type profileTemplateConfig struct {
|
||||||
ClusterZone string
|
ClusterZone string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToRoute returns a Proxy API Route, given a ServiceProfile Route.
|
||||||
func ToRoute(route *sp.RouteSpec) (*pb.Route, error) {
|
func ToRoute(route *sp.RouteSpec) (*pb.Route, error) {
|
||||||
cond, err := ToRequestMatch(route.Condition)
|
cond, err := ToRequestMatch(route.Condition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -38,6 +39,8 @@ func ToRoute(route *sp.RouteSpec) (*pb.Route, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToResponseClass returns a Proxy API ResponseClass, given a ServiceProfile
|
||||||
|
// ResponseClass.
|
||||||
func ToResponseClass(rc *sp.ResponseClass) (*pb.ResponseClass, error) {
|
func ToResponseClass(rc *sp.ResponseClass) (*pb.ResponseClass, error) {
|
||||||
cond, err := ToResponseMatch(rc.Condition)
|
cond, err := ToResponseMatch(rc.Condition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -49,6 +52,8 @@ func ToResponseClass(rc *sp.ResponseClass) (*pb.ResponseClass, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToResponseMatch returns a Proxy API ResponseMatch, given a ServiceProfile
|
||||||
|
// ResponseMatch.
|
||||||
func ToResponseMatch(rspMatch *sp.ResponseMatch) (*pb.ResponseMatch, error) {
|
func ToResponseMatch(rspMatch *sp.ResponseMatch) (*pb.ResponseMatch, error) {
|
||||||
if rspMatch == nil {
|
if rspMatch == nil {
|
||||||
return nil, errors.New("missing response match")
|
return nil, errors.New("missing response match")
|
||||||
|
@ -134,6 +139,8 @@ func ToResponseMatch(rspMatch *sp.ResponseMatch) (*pb.ResponseMatch, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToRequestMatch returns a Proxy API RequestMatch, given a ServiceProfile
|
||||||
|
// RequestMatch.
|
||||||
func ToRequestMatch(reqMatch *sp.RequestMatch) (*pb.RequestMatch, error) {
|
func ToRequestMatch(reqMatch *sp.RequestMatch) (*pb.RequestMatch, error) {
|
||||||
if reqMatch == nil {
|
if reqMatch == nil {
|
||||||
return nil, errors.New("missing request match")
|
return nil, errors.New("missing request match")
|
||||||
|
@ -226,6 +233,8 @@ func ToRequestMatch(reqMatch *sp.RequestMatch) (*pb.RequestMatch, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateRequestMatch validates whether a ServiceProfile RequestMatch has at
|
||||||
|
// least one field set.
|
||||||
func ValidateRequestMatch(reqMatch *sp.RequestMatch) error {
|
func ValidateRequestMatch(reqMatch *sp.RequestMatch) error {
|
||||||
matchKindSet := false
|
matchKindSet := false
|
||||||
if reqMatch.All != nil {
|
if reqMatch.All != nil {
|
||||||
|
@ -267,6 +276,8 @@ func ValidateRequestMatch(reqMatch *sp.RequestMatch) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateResponseMatch validates whether a ServiceProfile ResponseMatch has at
|
||||||
|
// least one field set, and sanity checks the Status Range.
|
||||||
func ValidateResponseMatch(rspMatch *sp.ResponseMatch) error {
|
func ValidateResponseMatch(rspMatch *sp.ResponseMatch) error {
|
||||||
invalidRangeErr := errors.New("Range maximum cannot be smaller than minimum")
|
invalidRangeErr := errors.New("Range maximum cannot be smaller than minimum")
|
||||||
matchKindSet := false
|
matchKindSet := false
|
||||||
|
@ -318,6 +329,8 @@ func buildConfig(namespace, service, controlPlaneNamespace string) *profileTempl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderProfileTemplate renders a ServiceProfile template to a buffer, given a
|
||||||
|
// namespace, service, and control plane namespace.
|
||||||
func RenderProfileTemplate(namespace, service, controlPlaneNamespace string, w io.Writer) error {
|
func RenderProfileTemplate(namespace, service, controlPlaneNamespace string, w io.Writer) error {
|
||||||
config := buildConfig(namespace, service, controlPlaneNamespace)
|
config := buildConfig(namespace, service, controlPlaneNamespace)
|
||||||
template, err := template.New("profile").Parse(Template)
|
template, err := template.New("profile").Parse(Template)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GenServiceProfile generates a mock ServiceProfile.
|
||||||
func GenServiceProfile(service, namespace, controlPlaneNamespace string) v1alpha1.ServiceProfile {
|
func GenServiceProfile(service, namespace, controlPlaneNamespace string) v1alpha1.ServiceProfile {
|
||||||
return v1alpha1.ServiceProfile{
|
return v1alpha1.ServiceProfile{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
@ -44,6 +45,7 @@ func GenServiceProfile(service, namespace, controlPlaneNamespace string) v1alpha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServiceProfileYamlEquals validates whether two ServiceProfiles are equal.
|
||||||
func ServiceProfileYamlEquals(actual, expected v1alpha1.ServiceProfile) error {
|
func ServiceProfileYamlEquals(actual, expected v1alpha1.ServiceProfile) error {
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
acutalYaml, err := yaml.Marshal(actual)
|
acutalYaml, err := yaml.Marshal(actual)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Supported TLS key types.
|
||||||
const (
|
const (
|
||||||
KeyTypeRSA = "rsa"
|
KeyTypeRSA = "rsa"
|
||||||
KeyTypeECDSA = "ecdsa"
|
KeyTypeECDSA = "ecdsa"
|
||||||
|
|
|
@ -37,6 +37,8 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckClientVersion validates whether the Linkerd Public API client's version
|
||||||
|
// matches an expected version.
|
||||||
func CheckClientVersion(expectedVersion string) error {
|
func CheckClientVersion(expectedVersion string) error {
|
||||||
if Version != expectedVersion {
|
if Version != expectedVersion {
|
||||||
return versionMismatchError(expectedVersion, Version)
|
return versionMismatchError(expectedVersion, Version)
|
||||||
|
@ -45,6 +47,8 @@ func CheckClientVersion(expectedVersion string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckServerVersion validates whether the Linkerd Public API server's version
|
||||||
|
// matches an expected version.
|
||||||
func CheckServerVersion(apiClient pb.ApiClient, expectedVersion string) error {
|
func CheckServerVersion(apiClient pb.ApiClient, expectedVersion string) error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -61,6 +65,8 @@ func CheckServerVersion(apiClient pb.ApiClient, expectedVersion string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLatestVersion performs an online request to check for the latest Linkerd
|
||||||
|
// version.
|
||||||
func GetLatestVersion(uuid string, source string) (string, error) {
|
func GetLatestVersion(uuid string, source string) (string, error) {
|
||||||
url := fmt.Sprintf(versionCheckURL, Version, uuid, source)
|
url := fmt.Sprintf(versionCheckURL, Version, uuid, source)
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
|
|
@ -29,6 +29,8 @@ func newRootOptions() *rootOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRootCmd returns a configured cobra.Command for the `proxy-init` command.
|
||||||
|
// TODO: consider moving this to `/proxy-init/main.go`
|
||||||
func NewRootCmd() *cobra.Command {
|
func NewRootCmd() *cobra.Command {
|
||||||
options := newRootOptions()
|
options := newRootOptions()
|
||||||
|
|
||||||
|
|
|
@ -10,16 +10,26 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RedirectAllMode = "redirect-all"
|
// RedirectAllMode indicates redirecting all ports.
|
||||||
RedirectListedMode = "redirect-listed"
|
RedirectAllMode = "redirect-all"
|
||||||
|
|
||||||
|
// RedirectListedMode indicates redirecting a given list of ports.
|
||||||
|
RedirectListedMode = "redirect-listed"
|
||||||
|
|
||||||
|
// IptablesPreroutingChainName specifies an iptables `PREROUTING` chain,
|
||||||
|
// responsible for packets that just arrived at the network interface.
|
||||||
IptablesPreroutingChainName = "PREROUTING"
|
IptablesPreroutingChainName = "PREROUTING"
|
||||||
IptablesOutputChainName = "OUTPUT"
|
|
||||||
|
// IptablesOutputChainName specifies an iptables `OUTPUT` chain.
|
||||||
|
IptablesOutputChainName = "OUTPUT"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// ExecutionTraceID provides a unique identifier for this script's execution.
|
||||||
ExecutionTraceID = strconv.Itoa(int(time.Now().Unix()))
|
ExecutionTraceID = strconv.Itoa(int(time.Now().Unix()))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FirewallConfiguration specifies how to configure a pod's iptables.
|
||||||
type FirewallConfiguration struct {
|
type FirewallConfiguration struct {
|
||||||
Mode string
|
Mode string
|
||||||
PortsToRedirectInbound []int
|
PortsToRedirectInbound []int
|
||||||
|
|
|
@ -20,6 +20,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// Server encapsulates the Linkerd control plane's web dashboard server.
|
||||||
Server struct {
|
Server struct {
|
||||||
templateDir string
|
templateDir string
|
||||||
staticDir string
|
staticDir string
|
||||||
|
@ -52,6 +53,9 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
s.router.ServeHTTP(w, req)
|
s.router.ServeHTTP(w, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewServer returns an initialized `http.Server`, configured to listen on an
|
||||||
|
// address, render templates, and serve static assets, for a given Linkerd
|
||||||
|
// control plane.
|
||||||
func NewServer(addr, templateDir, staticDir, uuid, controllerNamespace string, singleNamespace bool, webpackDevServer string, reload bool, apiClient pb.ApiClient) *http.Server {
|
func NewServer(addr, templateDir, staticDir, uuid, controllerNamespace string, singleNamespace bool, webpackDevServer string, reload bool, apiClient pb.ApiClient) *http.Server {
|
||||||
server := &Server{
|
server := &Server{
|
||||||
templateDir: templateDir,
|
templateDir: templateDir,
|
||||||
|
@ -118,6 +122,8 @@ func NewServer(addr, templateDir, staticDir, uuid, controllerNamespace string, s
|
||||||
return httpServer
|
return httpServer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderTemplate writes a rendered template into a buffer, given an HTTP
|
||||||
|
// request and template information.
|
||||||
func (s *Server) RenderTemplate(w http.ResponseWriter, templateFile, templateName string, args interface{}) error {
|
func (s *Server) RenderTemplate(w http.ResponseWriter, templateFile, templateName string, args interface{}) error {
|
||||||
log.Debugf("emitting template %s", templateFile)
|
log.Debugf("emitting template %s", templateFile)
|
||||||
template, err := s.loadTemplate(templateFile)
|
template, err := s.loadTemplate(templateFile)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package srv
|
package srv
|
||||||
|
|
||||||
|
// FakeServer provides a mock of a Server in `/web/srv`.
|
||||||
func FakeServer() Server {
|
func FakeServer() Server {
|
||||||
return Server{
|
return Server{
|
||||||
templateDir: "../templates",
|
templateDir: "../templates",
|
||||||
|
|
Loading…
Reference in New Issue