mirror of https://github.com/linkerd/linkerd2.git
Add namespace as a resource type in public-api (#760)
* Add namespace as a resource type in public-api The cli and public-api only supported deployments as a resource type. This change adds support for namespace as a resource type in the cli and public-api. This also change includes: - cli statsummary now prints `-`'s when objects are not in the mesh - cli statsummary prints `No resources found.` when applicable - removed `out-` from cli statsummary flags, and analagous proto changes - switched public-api to use native prometheus label types - misc error handling and logging fixes Part of #627 Signed-off-by: Andrew Seigner <siggy@buoyant.io> * Refactor filter and groupby label formulation Signed-off-by: Kevin Lingerfelt <kl@buoyant.io> * Rename stat_summary.go to stat.go in cli Signed-off-by: Kevin Lingerfelt <kl@buoyant.io> * Update rbac privileges for namespace stats Signed-off-by: Kevin Lingerfelt <kl@buoyant.io>
This commit is contained in:
parent
cc44db054f
commit
77fb6d3709
|
@ -5,6 +5,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
@ -13,13 +14,14 @@ import (
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/log"
|
||||||
"github.com/runconduit/conduit/controller/api/util"
|
"github.com/runconduit/conduit/controller/api/util"
|
||||||
pb "github.com/runconduit/conduit/controller/gen/public"
|
pb "github.com/runconduit/conduit/controller/gen/public"
|
||||||
|
"github.com/runconduit/conduit/pkg/k8s"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var timeWindow, namespace, resourceType, resourceName string
|
var timeWindow, namespace, resourceType, resourceName string
|
||||||
var outToNamespace, outToType, outToName string
|
var toNamespace, toType, toName string
|
||||||
var outFromNamespace, outFromType, outFromName string
|
var fromNamespace, fromType, fromName string
|
||||||
var allNamespaces bool
|
var allNamespaces bool
|
||||||
|
|
||||||
var statCmd = &cobra.Command{
|
var statCmd = &cobra.Command{
|
||||||
|
@ -29,7 +31,8 @@ var statCmd = &cobra.Command{
|
||||||
|
|
||||||
Valid resource types include:
|
Valid resource types include:
|
||||||
|
|
||||||
* deployment
|
* deployments
|
||||||
|
* namespaces
|
||||||
|
|
||||||
This command will hide resources that have completed, such as pods that are in the Succeeded or Failed phases.
|
This command will hide resources that have completed, such as pods that are in the Succeeded or Failed phases.
|
||||||
If no resource name is specified, displays stats about all resources of the specified RESOURCETYPE`,
|
If no resource name is specified, displays stats about all resources of the specified RESOURCETYPE`,
|
||||||
|
@ -37,9 +40,15 @@ If no resource name is specified, displays stats about all resources of the spec
|
||||||
conduit stat deployments -n test
|
conduit stat deployments -n test
|
||||||
|
|
||||||
# Get the hello1 deployment in the test namespace.
|
# Get the hello1 deployment in the test namespace.
|
||||||
conduit stat deployments hello1 -n test`,
|
conduit stat deployments hello1 -n test
|
||||||
|
|
||||||
|
# Get the test namespace.
|
||||||
|
conduit stat namespaces test
|
||||||
|
|
||||||
|
# Get all namespaces.
|
||||||
|
conduit stat --all-namespaces=true namespaces`,
|
||||||
Args: cobra.RangeArgs(1, 2),
|
Args: cobra.RangeArgs(1, 2),
|
||||||
ValidArgs: []string{"deployment"},
|
ValidArgs: []string{k8s.KubernetesDeployments, k8s.KubernetesNamespaces},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -71,12 +80,12 @@ func init() {
|
||||||
RootCmd.AddCommand(statCmd)
|
RootCmd.AddCommand(statCmd)
|
||||||
statCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "default", "Namespace of the specified resource")
|
statCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "default", "Namespace of the specified resource")
|
||||||
statCmd.PersistentFlags().StringVarP(&timeWindow, "time-window", "t", "1m", "Stat window (one of: \"10s\", \"1m\", \"10m\", \"1h\")")
|
statCmd.PersistentFlags().StringVarP(&timeWindow, "time-window", "t", "1m", "Stat window (one of: \"10s\", \"1m\", \"10m\", \"1h\")")
|
||||||
statCmd.PersistentFlags().StringVar(&outToName, "out-to", "", "If present, restricts outbound stats to the specified resource name")
|
statCmd.PersistentFlags().StringVar(&toName, "to", "", "If present, restricts outbound stats to the specified resource name")
|
||||||
statCmd.PersistentFlags().StringVar(&outToNamespace, "out-to-namespace", "", "Sets the namespace used to lookup the \"--out-to\" resource; by default the current \"--namespace\" is used")
|
statCmd.PersistentFlags().StringVar(&toNamespace, "to-namespace", "", "Sets the namespace used to lookup the \"--to\" resource; by default the current \"--namespace\" is used")
|
||||||
statCmd.PersistentFlags().StringVar(&outToType, "out-to-resource", "", "If present, restricts outbound stats to the specified resource type")
|
statCmd.PersistentFlags().StringVar(&toType, "to-resource", "", "Sets the resource type used to lookup the \"--to\" resource; by default the RESOURCETYPE is used")
|
||||||
statCmd.PersistentFlags().StringVar(&outFromName, "out-from", "", "If present, restricts outbound stats to the specified resource name")
|
statCmd.PersistentFlags().StringVar(&fromName, "from", "", "If present, restricts outbound stats from the specified resource name")
|
||||||
statCmd.PersistentFlags().StringVar(&outFromNamespace, "out-from-namespace", "", "Sets the namespace used to lookup the \"--out-from\" resource; by default the current \"--namespace\" is used")
|
statCmd.PersistentFlags().StringVar(&fromNamespace, "from-namespace", "", "Sets the namespace used from lookup the \"--from\" resource; by default the current \"--namespace\" is used")
|
||||||
statCmd.PersistentFlags().StringVar(&outFromType, "out-from-resource", "", "If present, restricts outbound stats to the specified resource type")
|
statCmd.PersistentFlags().StringVar(&fromType, "from-resource", "", "Sets the resource type used to lookup the \"--from\" resource; by default the RESOURCETYPE is used")
|
||||||
statCmd.PersistentFlags().BoolVar(&allNamespaces, "all-namespaces", false, "If present, returns stats across all namespaces, ignoring the \"--namespace\" flag")
|
statCmd.PersistentFlags().BoolVar(&allNamespaces, "all-namespaces", false, "If present, returns stats across all namespaces, ignoring the \"--namespace\" flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,8 +119,7 @@ func renderStats(resp *pb.StatSummaryResponse) string {
|
||||||
|
|
||||||
const padding = 3
|
const padding = 3
|
||||||
|
|
||||||
type row struct {
|
type rowStats struct {
|
||||||
meshed string
|
|
||||||
requestRate float64
|
requestRate float64
|
||||||
successRate float64
|
successRate float64
|
||||||
latencyP50 uint64
|
latencyP50 uint64
|
||||||
|
@ -119,6 +127,11 @@ type row struct {
|
||||||
latencyP99 uint64
|
latencyP99 uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type row struct {
|
||||||
|
meshed string
|
||||||
|
*rowStats
|
||||||
|
}
|
||||||
|
|
||||||
func writeStatsToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
|
func writeStatsToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
|
||||||
nameHeader := "NAME"
|
nameHeader := "NAME"
|
||||||
maxNameLength := len(nameHeader)
|
maxNameLength := len(nameHeader)
|
||||||
|
@ -147,15 +160,22 @@ func writeStatsToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Stats != nil {
|
if r.Stats != nil {
|
||||||
stats[key].requestRate = getRequestRate(*r)
|
stats[key].rowStats = &rowStats{
|
||||||
stats[key].successRate = getSuccessRate(*r)
|
requestRate: getRequestRate(*r),
|
||||||
stats[key].latencyP50 = r.Stats.LatencyMsP50
|
successRate: getSuccessRate(*r),
|
||||||
stats[key].latencyP95 = r.Stats.LatencyMsP95
|
latencyP50: r.Stats.LatencyMsP50,
|
||||||
stats[key].latencyP99 = r.Stats.LatencyMsP99
|
latencyP95: r.Stats.LatencyMsP95,
|
||||||
|
latencyP99: r.Stats.LatencyMsP99,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(stats) == 0 {
|
||||||
|
fmt.Fprintln(os.Stderr, "No traffic found.")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
headers := make([]string, 0)
|
headers := make([]string, 0)
|
||||||
if allNamespaces {
|
if allNamespaces {
|
||||||
headers = append(headers,
|
headers = append(headers,
|
||||||
|
@ -170,6 +190,7 @@ func writeStatsToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
|
||||||
"LATENCY_P95",
|
"LATENCY_P95",
|
||||||
"LATENCY_P99\t", // trailing \t is required to format last column
|
"LATENCY_P99\t", // trailing \t is required to format last column
|
||||||
}...)
|
}...)
|
||||||
|
|
||||||
fmt.Fprintln(w, strings.Join(headers, "\t"))
|
fmt.Fprintln(w, strings.Join(headers, "\t"))
|
||||||
|
|
||||||
sortedKeys := sortStatsKeys(stats)
|
sortedKeys := sortStatsKeys(stats)
|
||||||
|
@ -179,23 +200,32 @@ func writeStatsToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
|
||||||
name := parts[1]
|
name := parts[1]
|
||||||
values := make([]interface{}, 0)
|
values := make([]interface{}, 0)
|
||||||
templateString := "%s\t%s\t%.2f%%\t%.1frps\t%dms\t%dms\t%dms\t\n"
|
templateString := "%s\t%s\t%.2f%%\t%.1frps\t%dms\t%dms\t%dms\t\n"
|
||||||
|
templateStringEmpty := "%s\t%s\t-\t-\t-\t-\t-\t\n"
|
||||||
|
|
||||||
if allNamespaces {
|
if allNamespaces {
|
||||||
values = append(values,
|
values = append(values,
|
||||||
namespace+strings.Repeat(" ", maxNamespaceLength-len(namespace)))
|
namespace+strings.Repeat(" ", maxNamespaceLength-len(namespace)))
|
||||||
templateString = "%s\t" + templateString
|
templateString = "%s\t" + templateString
|
||||||
|
templateStringEmpty = "%s\t" + templateStringEmpty
|
||||||
}
|
}
|
||||||
values = append(values, []interface{}{
|
values = append(values, []interface{}{
|
||||||
name + strings.Repeat(" ", maxNameLength-len(name)),
|
name + strings.Repeat(" ", maxNameLength-len(name)),
|
||||||
stats[key].meshed,
|
stats[key].meshed,
|
||||||
stats[key].successRate * 100,
|
|
||||||
stats[key].requestRate,
|
|
||||||
stats[key].latencyP50,
|
|
||||||
stats[key].latencyP95,
|
|
||||||
stats[key].latencyP99,
|
|
||||||
}...)
|
}...)
|
||||||
|
|
||||||
fmt.Fprintf(w, templateString, values...)
|
if stats[key].rowStats != nil {
|
||||||
|
values = append(values, []interface{}{
|
||||||
|
stats[key].successRate * 100,
|
||||||
|
stats[key].requestRate,
|
||||||
|
stats[key].latencyP50,
|
||||||
|
stats[key].latencyP95,
|
||||||
|
stats[key].latencyP99,
|
||||||
|
}...)
|
||||||
|
|
||||||
|
fmt.Fprintf(w, templateString, values...)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, templateStringEmpty, values...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,16 +238,16 @@ func buildStatSummaryRequest() (*pb.StatSummaryRequest, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
requestParams := util.StatSummaryRequestParams{
|
requestParams := util.StatSummaryRequestParams{
|
||||||
TimeWindow: timeWindow,
|
TimeWindow: timeWindow,
|
||||||
ResourceName: resourceName,
|
ResourceName: resourceName,
|
||||||
ResourceType: resourceType,
|
ResourceType: resourceType,
|
||||||
Namespace: targetNamespace,
|
Namespace: targetNamespace,
|
||||||
OutToName: outToName,
|
ToName: toName,
|
||||||
OutToType: outToType,
|
ToType: toType,
|
||||||
OutToNamespace: outToNamespace,
|
ToNamespace: toNamespace,
|
||||||
OutFromName: outFromName,
|
FromName: fromName,
|
||||||
OutFromType: outFromType,
|
FromType: fromType,
|
||||||
OutFromNamespace: outFromNamespace,
|
FromNamespace: fromNamespace,
|
||||||
}
|
}
|
||||||
|
|
||||||
return util.BuildStatSummaryRequest(requestParams)
|
return util.BuildStatSummaryRequest(requestParams)
|
|
@ -23,7 +23,7 @@ rules:
|
||||||
resources: ["deployments", "replicasets"]
|
resources: ["deployments", "replicasets"]
|
||||||
verbs: ["list", "get", "watch"]
|
verbs: ["list", "get", "watch"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["pods", "endpoints", "services"]
|
resources: ["pods", "endpoints", "services", "namespaces"]
|
||||||
verbs: ["list", "get", "watch"]
|
verbs: ["list", "get", "watch"]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -23,7 +23,7 @@ rules:
|
||||||
resources: ["deployments", "replicasets"]
|
resources: ["deployments", "replicasets"]
|
||||||
verbs: ["list", "get", "watch"]
|
verbs: ["list", "get", "watch"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["pods", "endpoints", "services"]
|
resources: ["pods", "endpoints", "services", "namespaces"]
|
||||||
verbs: ["list", "get", "watch"]
|
verbs: ["list", "get", "watch"]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -26,7 +26,7 @@ rules:
|
||||||
resources: ["deployments", "replicasets"]
|
resources: ["deployments", "replicasets"]
|
||||||
verbs: ["list", "get", "watch"]
|
verbs: ["list", "get", "watch"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["pods", "endpoints", "services"]
|
resources: ["pods", "endpoints", "services", "namespaces"]
|
||||||
verbs: ["list", "get", "watch"]
|
verbs: ["list", "get", "watch"]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (c *grpcOverHttpClient) Tap(ctx context.Context, req *pb.TapRequest, _ ...g
|
||||||
func (c *grpcOverHttpClient) apiRequest(ctx context.Context, endpoint string, req proto.Message, protoResponse proto.Message) error {
|
func (c *grpcOverHttpClient) apiRequest(ctx context.Context, endpoint string, req proto.Message, protoResponse proto.Message) error {
|
||||||
url := c.endpointNameToPublicApiUrl(endpoint)
|
url := c.endpointNameToPublicApiUrl(endpoint)
|
||||||
|
|
||||||
log.Debugf("Making gRPC-over-HTTP call to [%s]", url.String())
|
log.Debugf("Making gRPC-over-HTTP call to [%s] [%+v]", url.String(), req)
|
||||||
httpRsp, err := c.post(ctx, url, req)
|
httpRsp, err := c.post(ctx, url, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -24,6 +24,7 @@ type (
|
||||||
grpcServer struct {
|
grpcServer struct {
|
||||||
prometheusAPI promv1.API
|
prometheusAPI promv1.API
|
||||||
tapClient tapPb.TapClient
|
tapClient tapPb.TapClient
|
||||||
|
namespaceLister corelisters.NamespaceLister
|
||||||
deployLister applisters.DeploymentLister
|
deployLister applisters.DeploymentLister
|
||||||
replicaSetLister applisters.ReplicaSetLister
|
replicaSetLister applisters.ReplicaSetLister
|
||||||
podLister corelisters.PodLister
|
podLister corelisters.PodLister
|
||||||
|
@ -43,6 +44,7 @@ const (
|
||||||
func newGrpcServer(
|
func newGrpcServer(
|
||||||
promAPI promv1.API,
|
promAPI promv1.API,
|
||||||
tapClient tapPb.TapClient,
|
tapClient tapPb.TapClient,
|
||||||
|
namespaceLister corelisters.NamespaceLister,
|
||||||
deployLister applisters.DeploymentLister,
|
deployLister applisters.DeploymentLister,
|
||||||
replicaSetLister applisters.ReplicaSetLister,
|
replicaSetLister applisters.ReplicaSetLister,
|
||||||
podLister corelisters.PodLister,
|
podLister corelisters.PodLister,
|
||||||
|
@ -52,6 +54,7 @@ func newGrpcServer(
|
||||||
return &grpcServer{
|
return &grpcServer{
|
||||||
prometheusAPI: promAPI,
|
prometheusAPI: promAPI,
|
||||||
tapClient: tapClient,
|
tapClient: tapClient,
|
||||||
|
namespaceLister: namespaceLister,
|
||||||
deployLister: deployLister,
|
deployLister: deployLister,
|
||||||
replicaSetLister: replicaSetLister,
|
replicaSetLister: replicaSetLister,
|
||||||
podLister: podLister,
|
podLister: podLister,
|
||||||
|
|
|
@ -166,6 +166,7 @@ spec:
|
||||||
clientSet := fake.NewSimpleClientset(k8sObjs...)
|
clientSet := fake.NewSimpleClientset(k8sObjs...)
|
||||||
sharedInformers := informers.NewSharedInformerFactory(clientSet, 10*time.Minute)
|
sharedInformers := informers.NewSharedInformerFactory(clientSet, 10*time.Minute)
|
||||||
|
|
||||||
|
namespaceInformer := sharedInformers.Core().V1().Namespaces()
|
||||||
deployInformer := sharedInformers.Apps().V1beta2().Deployments()
|
deployInformer := sharedInformers.Apps().V1beta2().Deployments()
|
||||||
replicaSetInformer := sharedInformers.Apps().V1beta2().ReplicaSets()
|
replicaSetInformer := sharedInformers.Apps().V1beta2().ReplicaSets()
|
||||||
podInformer := sharedInformers.Core().V1().Pods()
|
podInformer := sharedInformers.Core().V1().Pods()
|
||||||
|
@ -173,6 +174,7 @@ spec:
|
||||||
fakeGrpcServer := newGrpcServer(
|
fakeGrpcServer := newGrpcServer(
|
||||||
&MockProm{Res: exp.promRes},
|
&MockProm{Res: exp.promRes},
|
||||||
tap.NewTapClient(nil),
|
tap.NewTapClient(nil),
|
||||||
|
namespaceInformer.Lister(),
|
||||||
deployInformer.Lister(),
|
deployInformer.Lister(),
|
||||||
replicaSetInformer.Lister(),
|
replicaSetInformer.Lister(),
|
||||||
podInformer.Lister(),
|
podInformer.Lister(),
|
||||||
|
@ -183,6 +185,7 @@ spec:
|
||||||
sharedInformers.Start(stopCh)
|
sharedInformers.Start(stopCh)
|
||||||
if !cache.WaitForCacheSync(
|
if !cache.WaitForCacheSync(
|
||||||
stopCh,
|
stopCh,
|
||||||
|
namespaceInformer.Informer().HasSynced,
|
||||||
deployInformer.Informer().HasSynced,
|
deployInformer.Informer().HasSynced,
|
||||||
replicaSetInformer.Informer().HasSynced,
|
replicaSetInformer.Informer().HasSynced,
|
||||||
podInformer.Informer().HasSynced,
|
podInformer.Informer().HasSynced,
|
||||||
|
|
|
@ -199,6 +199,7 @@ func NewServer(
|
||||||
addr string,
|
addr string,
|
||||||
prometheusClient promApi.Client,
|
prometheusClient promApi.Client,
|
||||||
tapClient tapPb.TapClient,
|
tapClient tapPb.TapClient,
|
||||||
|
namespaceLister corelisters.NamespaceLister,
|
||||||
deployLister applisters.DeploymentLister,
|
deployLister applisters.DeploymentLister,
|
||||||
replicaSetLister applisters.ReplicaSetLister,
|
replicaSetLister applisters.ReplicaSetLister,
|
||||||
podLister corelisters.PodLister,
|
podLister corelisters.PodLister,
|
||||||
|
@ -209,6 +210,7 @@ func NewServer(
|
||||||
grpcServer: newGrpcServer(
|
grpcServer: newGrpcServer(
|
||||||
promv1.NewAPI(prometheusClient),
|
promv1.NewAPI(prometheusClient),
|
||||||
tapClient,
|
tapClient,
|
||||||
|
namespaceLister,
|
||||||
deployLister,
|
deployLister,
|
||||||
replicaSetLister,
|
replicaSetLister,
|
||||||
podLister,
|
podLister,
|
||||||
|
|
|
@ -2,7 +2,6 @@ package public
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -15,6 +14,7 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
@ -28,22 +28,24 @@ type promResult struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
reqQuery = "sum(increase(response_total{%s}[%s])) by (%s, namespace, classification)"
|
reqQuery = "sum(increase(response_total%s[%s])) by (%s, classification)"
|
||||||
latencyQuantileQuery = "histogram_quantile(%s, sum(irate(response_latency_ms_bucket{%s}[%s])) by (le, namespace, %s))"
|
latencyQuantileQuery = "histogram_quantile(%s, sum(irate(response_latency_ms_bucket%s[%s])) by (le, %s))"
|
||||||
|
|
||||||
promRequests = promType("QUERY_REQUESTS")
|
promRequests = promType("QUERY_REQUESTS")
|
||||||
promLatencyP50 = promType("0.5")
|
promLatencyP50 = promType("0.5")
|
||||||
promLatencyP95 = promType("0.95")
|
promLatencyP95 = promType("0.95")
|
||||||
promLatencyP99 = promType("0.99")
|
promLatencyP99 = promType("0.99")
|
||||||
|
|
||||||
namespaceLabel = "namespace"
|
namespaceLabel = model.LabelName("namespace")
|
||||||
|
dstNamespaceLabel = model.LabelName("dst_namespace")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
promTypes = []promType{promRequests, promLatencyP50, promLatencyP95, promLatencyP99}
|
promTypes = []promType{promRequests, promLatencyP50, promLatencyP95, promLatencyP99}
|
||||||
|
|
||||||
k8sResourceTypesToPromLabels = map[string]string{
|
k8sResourceTypesToPromLabels = map[string]model.LabelName{
|
||||||
k8s.KubernetesDeployments: "deployment",
|
k8s.KubernetesDeployments: "deployment",
|
||||||
|
k8s.KubernetesNamespaces: namespaceLabel,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -53,15 +55,31 @@ type meshedCount struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *grpcServer) StatSummary(ctx context.Context, req *pb.StatSummaryRequest) (*pb.StatSummaryResponse, error) {
|
func (s *grpcServer) StatSummary(ctx context.Context, req *pb.StatSummaryRequest) (*pb.StatSummaryResponse, error) {
|
||||||
|
var err error
|
||||||
|
var objectMap map[string]metav1.ObjectMeta
|
||||||
|
var meshCount map[string]*meshedCount
|
||||||
|
|
||||||
switch req.Selector.Resource.Type {
|
switch req.Selector.Resource.Type {
|
||||||
case k8s.KubernetesDeployments:
|
case k8s.KubernetesDeployments:
|
||||||
return s.deploymentQuery(ctx, req)
|
objectMap, meshCount, err = s.getDeployments(req.Selector.Resource)
|
||||||
|
case k8s.KubernetesNamespaces:
|
||||||
|
objectMap, meshCount, err = s.getNamespaces(req.Selector.Resource)
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("Unimplemented resource type: " + req.Selector.Resource.Type)
|
err = fmt.Errorf("Unimplemented resource type: %v", req.Selector.Resource.Type)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.objectQuery(ctx, req, objectMap, meshCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *grpcServer) deploymentQuery(ctx context.Context, req *pb.StatSummaryRequest) (*pb.StatSummaryResponse, error) {
|
func (s *grpcServer) objectQuery(
|
||||||
|
ctx context.Context,
|
||||||
|
req *pb.StatSummaryRequest,
|
||||||
|
objects map[string]metav1.ObjectMeta,
|
||||||
|
meshCount map[string]*meshedCount,
|
||||||
|
) (*pb.StatSummaryResponse, error) {
|
||||||
rows := make([]*pb.StatTable_PodGroup_Row, 0)
|
rows := make([]*pb.StatTable_PodGroup_Row, 0)
|
||||||
|
|
||||||
timeWindow, err := apiUtil.GetWindowString(req.TimeWindow)
|
timeWindow, err := apiUtil.GetWindowString(req.TimeWindow)
|
||||||
|
@ -69,23 +87,29 @@ func (s *grpcServer) deploymentQuery(ctx context.Context, req *pb.StatSummaryReq
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
deployments, meshCount, err := s.getDeployments(req.Selector.Resource)
|
requestMetrics, err := s.getRequests(ctx, req, timeWindow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
requestLabels := buildRequestLabels(req)
|
var keys []string
|
||||||
groupBy := promResourceType(req.Selector.Resource)
|
|
||||||
|
|
||||||
requestMetrics, err := s.getRequests(ctx, requestLabels, groupBy, timeWindow)
|
if req.GetOutbound() == nil || req.GetNone() != nil {
|
||||||
if err != nil {
|
// if this request doesn't have outbound filtering, return all rows
|
||||||
return nil, err
|
for key := range objects {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// otherwise only return rows for which we have stats
|
||||||
|
for key := range requestMetrics {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, resource := range deployments {
|
for _, key := range keys {
|
||||||
key, err := cache.MetaNamespaceKeyFunc(resource)
|
resource, ok := objects[key]
|
||||||
if err != nil {
|
if !ok {
|
||||||
return nil, err
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
row := pb.StatTable_PodGroup_Row{
|
row := pb.StatTable_PodGroup_Row{
|
||||||
|
@ -125,74 +149,82 @@ func (s *grpcServer) deploymentQuery(ctx context.Context, req *pb.StatSummaryReq
|
||||||
return &rsp, nil
|
return &rsp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func promLabel(key, val string) string {
|
func promLabelNames(resource *pb.Resource) model.LabelNames {
|
||||||
return fmt.Sprintf("%s=\"%s\"", key, val)
|
names := model.LabelNames{namespaceLabel}
|
||||||
|
if resource.Type != k8s.KubernetesNamespaces {
|
||||||
|
names = append(names, promResourceType(resource))
|
||||||
|
}
|
||||||
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
func promNameLabel(resource *pb.Resource) string {
|
func promDstLabelNames(resource *pb.Resource) model.LabelNames {
|
||||||
return promLabel(promResourceType(resource), resource.Name)
|
names := model.LabelNames{dstNamespaceLabel}
|
||||||
|
if resource.Type != k8s.KubernetesNamespaces {
|
||||||
|
names = append(names, "dst_"+promResourceType(resource))
|
||||||
|
}
|
||||||
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
func promNamespaceLabel(resource *pb.Resource) string {
|
func promLabels(resource *pb.Resource) model.LabelSet {
|
||||||
return promLabel(namespaceLabel, resource.Namespace)
|
set := model.LabelSet{}
|
||||||
|
if resource.Name != "" {
|
||||||
|
set[promResourceType(resource)] = model.LabelValue(resource.Name)
|
||||||
|
}
|
||||||
|
if resource.Type != k8s.KubernetesNamespaces && resource.Namespace != "" {
|
||||||
|
set[namespaceLabel] = model.LabelValue(resource.Namespace)
|
||||||
|
}
|
||||||
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
func promDstLabels(resource *pb.Resource) []string {
|
func promDstLabels(resource *pb.Resource) model.LabelSet {
|
||||||
return []string{
|
set := model.LabelSet{}
|
||||||
promLabel("dst_"+namespaceLabel, resource.Namespace),
|
if resource.Name != "" {
|
||||||
promLabel("dst_"+promResourceType(resource), resource.Name),
|
set["dst_"+promResourceType(resource)] = model.LabelValue(resource.Name)
|
||||||
|
}
|
||||||
|
if resource.Type != k8s.KubernetesNamespaces && resource.Namespace != "" {
|
||||||
|
set[dstNamespaceLabel] = model.LabelValue(resource.Namespace)
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
func promDirectionLabels(direction string) model.LabelSet {
|
||||||
|
return model.LabelSet{
|
||||||
|
model.LabelName("direction"): model.LabelValue(direction),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func promResourceType(resource *pb.Resource) string {
|
func promResourceType(resource *pb.Resource) model.LabelName {
|
||||||
return k8sResourceTypesToPromLabels[resource.Type]
|
return k8sResourceTypesToPromLabels[resource.Type]
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildRequestLabels(req *pb.StatSummaryRequest) string {
|
func buildRequestLabels(req *pb.StatSummaryRequest) (model.LabelSet, model.LabelNames) {
|
||||||
labels := []string{}
|
labels := model.LabelSet{}
|
||||||
|
aggregations := model.LabelNames{}
|
||||||
|
|
||||||
var direction string
|
switch out := req.Outbound.(type) {
|
||||||
switch req.Outbound.(type) {
|
case *pb.StatSummaryRequest_ToResource:
|
||||||
case *pb.StatSummaryRequest_OutToResource:
|
aggregations = promLabelNames(req.Selector.Resource)
|
||||||
direction = "outbound"
|
labels = labels.Merge(promDstLabels(out.ToResource))
|
||||||
labels = append(labels, promDstLabels(req.GetOutToResource())...)
|
labels = labels.Merge(promLabels(req.Selector.Resource))
|
||||||
|
labels = labels.Merge(promDirectionLabels("outbound"))
|
||||||
|
|
||||||
case *pb.StatSummaryRequest_OutFromResource:
|
case *pb.StatSummaryRequest_FromResource:
|
||||||
direction = "outbound"
|
aggregations = promDstLabelNames(req.Selector.Resource)
|
||||||
labels = append(labels, promDstLabels(req.Selector.Resource)...)
|
labels = labels.Merge(promLabels(out.FromResource))
|
||||||
|
labels = labels.Merge(promDirectionLabels("outbound"))
|
||||||
outFromNs := req.GetOutFromResource().Namespace
|
|
||||||
if outFromNs == "" {
|
|
||||||
outFromNs = req.Selector.Resource.Namespace
|
|
||||||
}
|
|
||||||
|
|
||||||
if outFromNs != "" {
|
|
||||||
labels = append(labels, promLabel(namespaceLabel, outFromNs))
|
|
||||||
}
|
|
||||||
if req.Selector.Resource.Name != "" {
|
|
||||||
labels = append(labels, promNameLabel(req.GetOutFromResource()))
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
direction = "inbound"
|
aggregations = promLabelNames(req.Selector.Resource)
|
||||||
|
labels = labels.Merge(promLabels(req.Selector.Resource))
|
||||||
|
labels = labels.Merge(promDirectionLabels("inbound"))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// it's weird to check this again outside the switch, but including this code
|
return labels, aggregations
|
||||||
// in the other three switch branches is very repetitive
|
|
||||||
if req.GetOutFromResource() == nil {
|
|
||||||
if req.Selector.Resource.Namespace != "" {
|
|
||||||
labels = append(labels, promNamespaceLabel(req.Selector.Resource))
|
|
||||||
}
|
|
||||||
if req.Selector.Resource.Name != "" {
|
|
||||||
labels = append(labels, promNameLabel(req.Selector.Resource))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
labels = append(labels, promLabel("direction", direction))
|
|
||||||
|
|
||||||
return strings.Join(labels, ",")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *grpcServer) getRequests(ctx context.Context, reqLabels string, groupBy string, timeWindow string) (map[string]*pb.BasicStats, error) {
|
func (s *grpcServer) getRequests(ctx context.Context, req *pb.StatSummaryRequest, timeWindow string) (map[string]*pb.BasicStats, error) {
|
||||||
|
reqLabels, groupBy := buildRequestLabels(req)
|
||||||
resultChan := make(chan promResult)
|
resultChan := make(chan promResult)
|
||||||
|
|
||||||
// kick off 4 asynchronous queries: 1 request volume + 3 latency
|
// kick off 4 asynchronous queries: 1 request volume + 3 latency
|
||||||
|
@ -226,7 +258,7 @@ func (s *grpcServer) getRequests(ctx context.Context, reqLabels string, groupBy
|
||||||
for i := 0; i < len(promTypes); i++ {
|
for i := 0; i < len(promTypes); i++ {
|
||||||
result := <-resultChan
|
result := <-resultChan
|
||||||
if result.err != nil {
|
if result.err != nil {
|
||||||
log.Errorf("queryProm failed with: %s", err)
|
log.Errorf("queryProm failed with: %s", result.err)
|
||||||
err = result.err
|
err = result.err
|
||||||
} else {
|
} else {
|
||||||
results = append(results, result)
|
results = append(results, result)
|
||||||
|
@ -239,12 +271,12 @@ func (s *grpcServer) getRequests(ctx context.Context, reqLabels string, groupBy
|
||||||
return processRequests(results, groupBy), nil
|
return processRequests(results, groupBy), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processRequests(results []promResult, labelSelector string) map[string]*pb.BasicStats {
|
func processRequests(results []promResult, groupBy model.LabelNames) map[string]*pb.BasicStats {
|
||||||
basicStats := make(map[string]*pb.BasicStats)
|
basicStats := make(map[string]*pb.BasicStats)
|
||||||
|
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
for _, sample := range result.vec {
|
for _, sample := range result.vec {
|
||||||
label := metricToKey(sample.Metric, labelSelector)
|
label := metricToKey(sample.Metric, groupBy)
|
||||||
if basicStats[label] == nil {
|
if basicStats[label] == nil {
|
||||||
basicStats[label] = &pb.BasicStats{}
|
basicStats[label] = &pb.BasicStats{}
|
||||||
}
|
}
|
||||||
|
@ -275,18 +307,15 @@ func processRequests(results []promResult, labelSelector string) map[string]*pb.
|
||||||
return basicStats
|
return basicStats
|
||||||
}
|
}
|
||||||
|
|
||||||
func metricToKey(metric model.Metric, labelSelector string) string {
|
func metricToKey(metric model.Metric, groupBy model.LabelNames) string {
|
||||||
if metric[model.LabelName(namespaceLabel)] == "" {
|
values := []string{}
|
||||||
return string(metric[model.LabelName(labelSelector)])
|
for _, k := range groupBy {
|
||||||
|
values = append(values, string(metric[k]))
|
||||||
}
|
}
|
||||||
|
return strings.Join(values, "/")
|
||||||
return fmt.Sprintf("%s/%s",
|
|
||||||
metric[model.LabelName(namespaceLabel)],
|
|
||||||
metric[model.LabelName(labelSelector)],
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *grpcServer) getDeployments(res *pb.Resource) ([]*appsv1beta2.Deployment, map[string]*meshedCount, error) {
|
func (s *grpcServer) getDeployments(res *pb.Resource) (map[string]metav1.ObjectMeta, map[string]*meshedCount, error) {
|
||||||
var err error
|
var err error
|
||||||
var deployments []*appsv1beta2.Deployment
|
var deployments []*appsv1beta2.Deployment
|
||||||
|
|
||||||
|
@ -305,22 +334,59 @@ func (s *grpcServer) getDeployments(res *pb.Resource) ([]*appsv1beta2.Deployment
|
||||||
}
|
}
|
||||||
|
|
||||||
meshedPodCount := make(map[string]*meshedCount)
|
meshedPodCount := make(map[string]*meshedCount)
|
||||||
|
deploymentMap := make(map[string]metav1.ObjectMeta)
|
||||||
for _, deployment := range deployments {
|
for _, deployment := range deployments {
|
||||||
meshCount, err := s.getMeshedPodCount(deployment.Namespace, deployment)
|
key, err := cache.MetaNamespaceKeyFunc(deployment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
key, err := cache.MetaNamespaceKeyFunc(deployment)
|
deploymentMap[key] = deployment.ObjectMeta
|
||||||
|
|
||||||
|
meshCount, err := s.getMeshedPodCount(deployment.Namespace, deployment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
meshedPodCount[key] = meshCount
|
meshedPodCount[key] = meshCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return deployments, meshedPodCount, nil
|
return deploymentMap, meshedPodCount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *grpcServer) getNamespaces(res *pb.Resource) (map[string]metav1.ObjectMeta, map[string]*meshedCount, error) {
|
||||||
|
var err error
|
||||||
|
var namespaces []*apiv1.Namespace
|
||||||
|
|
||||||
|
if res.Name == "" {
|
||||||
|
namespaces, err = s.namespaceLister.List(labels.Everything())
|
||||||
|
} else {
|
||||||
|
var namespace *apiv1.Namespace
|
||||||
|
namespace, err = s.namespaceLister.Get(res.Name)
|
||||||
|
namespaces = []*apiv1.Namespace{namespace}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
meshedPodCount := make(map[string]*meshedCount)
|
||||||
|
namespaceMap := make(map[string]metav1.ObjectMeta)
|
||||||
|
for _, namespace := range namespaces {
|
||||||
|
key, err := cache.MetaNamespaceKeyFunc(namespace)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
namespaceMap[key] = namespace.ObjectMeta
|
||||||
|
|
||||||
|
meshCount, err := s.getMeshedPodCount(namespace.Name, namespace)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
meshedPodCount[key] = meshCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return namespaceMap, meshedPodCount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// this takes a long time for namespaces with many pods
|
|
||||||
func (s *grpcServer) getMeshedPodCount(namespace string, obj runtime.Object) (*meshedCount, error) {
|
func (s *grpcServer) getMeshedPodCount(namespace string, obj runtime.Object) (*meshedCount, error) {
|
||||||
selector, err := getSelectorFromObject(obj)
|
selector, err := getSelectorFromObject(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -350,6 +416,9 @@ func isInMesh(pod *apiv1.Pod) bool {
|
||||||
|
|
||||||
func getSelectorFromObject(obj runtime.Object) (labels.Selector, error) {
|
func getSelectorFromObject(obj runtime.Object) (labels.Selector, error) {
|
||||||
switch typed := obj.(type) {
|
switch typed := obj.(type) {
|
||||||
|
case *apiv1.Namespace:
|
||||||
|
return labels.Everything(), nil
|
||||||
|
|
||||||
case *appsv1beta2.Deployment:
|
case *appsv1beta2.Deployment:
|
||||||
return labels.Set(typed.Spec.Selector.MatchLabels).AsSelector(), nil
|
return labels.Set(typed.Spec.Selector.MatchLabels).AsSelector(), nil
|
||||||
|
|
||||||
|
@ -364,7 +433,7 @@ func (s *grpcServer) queryProm(ctx context.Context, query string) (model.Vector,
|
||||||
// single data point (aka summary) query
|
// single data point (aka summary) query
|
||||||
res, err := s.prometheusAPI.Query(ctx, query, time.Time{})
|
res, err := s.prometheusAPI.Query(ctx, query, time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Query(%+v, %+v) failed with: %+v", query, err)
|
log.Errorf("Query(%+v) failed with: %+v", query, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.Debugf("Query response: %+v", res)
|
log.Debugf("Query response: %+v", res)
|
||||||
|
|
|
@ -136,6 +136,7 @@ metadata:
|
||||||
clientSet := fake.NewSimpleClientset(k8sObjs...)
|
clientSet := fake.NewSimpleClientset(k8sObjs...)
|
||||||
sharedInformers := informers.NewSharedInformerFactory(clientSet, 10*time.Minute)
|
sharedInformers := informers.NewSharedInformerFactory(clientSet, 10*time.Minute)
|
||||||
|
|
||||||
|
namespaceInformer := sharedInformers.Core().V1().Namespaces()
|
||||||
deployInformer := sharedInformers.Apps().V1beta2().Deployments()
|
deployInformer := sharedInformers.Apps().V1beta2().Deployments()
|
||||||
replicaSetInformer := sharedInformers.Apps().V1beta2().ReplicaSets()
|
replicaSetInformer := sharedInformers.Apps().V1beta2().ReplicaSets()
|
||||||
podInformer := sharedInformers.Core().V1().Pods()
|
podInformer := sharedInformers.Core().V1().Pods()
|
||||||
|
@ -143,6 +144,7 @@ metadata:
|
||||||
fakeGrpcServer := newGrpcServer(
|
fakeGrpcServer := newGrpcServer(
|
||||||
&MockProm{Res: exp.promRes},
|
&MockProm{Res: exp.promRes},
|
||||||
tap.NewTapClient(nil),
|
tap.NewTapClient(nil),
|
||||||
|
namespaceInformer.Lister(),
|
||||||
deployInformer.Lister(),
|
deployInformer.Lister(),
|
||||||
replicaSetInformer.Lister(),
|
replicaSetInformer.Lister(),
|
||||||
podInformer.Lister(),
|
podInformer.Lister(),
|
||||||
|
@ -153,6 +155,7 @@ metadata:
|
||||||
sharedInformers.Start(stopCh)
|
sharedInformers.Start(stopCh)
|
||||||
if !cache.WaitForCacheSync(
|
if !cache.WaitForCacheSync(
|
||||||
stopCh,
|
stopCh,
|
||||||
|
namespaceInformer.Informer().HasSynced,
|
||||||
deployInformer.Informer().HasSynced,
|
deployInformer.Informer().HasSynced,
|
||||||
replicaSetInformer.Informer().HasSynced,
|
replicaSetInformer.Informer().HasSynced,
|
||||||
podInformer.Informer().HasSynced,
|
podInformer.Informer().HasSynced,
|
||||||
|
@ -211,6 +214,7 @@ metadata:
|
||||||
fakeGrpcServer := newGrpcServer(
|
fakeGrpcServer := newGrpcServer(
|
||||||
&MockProm{Res: exp.promRes},
|
&MockProm{Res: exp.promRes},
|
||||||
tap.NewTapClient(nil),
|
tap.NewTapClient(nil),
|
||||||
|
sharedInformers.Core().V1().Namespaces().Lister(),
|
||||||
sharedInformers.Apps().V1beta2().Deployments().Lister(),
|
sharedInformers.Apps().V1beta2().Deployments().Lister(),
|
||||||
sharedInformers.Apps().V1beta2().ReplicaSets().Lister(),
|
sharedInformers.Apps().V1beta2().ReplicaSets().Lister(),
|
||||||
sharedInformers.Core().V1().Pods().Lister(),
|
sharedInformers.Core().V1().Pods().Lister(),
|
||||||
|
|
|
@ -45,16 +45,16 @@ func GetWindowString(timeWindow pb.TimeWindow) (string, error) {
|
||||||
var defaultMetricTimeWindow = pb.TimeWindow_ONE_MIN
|
var defaultMetricTimeWindow = pb.TimeWindow_ONE_MIN
|
||||||
|
|
||||||
type StatSummaryRequestParams struct {
|
type StatSummaryRequestParams struct {
|
||||||
TimeWindow string
|
TimeWindow string
|
||||||
Namespace string
|
Namespace string
|
||||||
ResourceType string
|
ResourceType string
|
||||||
ResourceName string
|
ResourceName string
|
||||||
OutToNamespace string
|
ToNamespace string
|
||||||
OutToType string
|
ToType string
|
||||||
OutToName string
|
ToName string
|
||||||
OutFromNamespace string
|
FromNamespace string
|
||||||
OutFromType string
|
FromType string
|
||||||
OutFromName string
|
FromName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildStatSummaryRequest(p StatSummaryRequestParams) (*pb.StatSummaryRequest, error) {
|
func BuildStatSummaryRequest(p StatSummaryRequestParams) (*pb.StatSummaryRequest, error) {
|
||||||
|
@ -83,34 +83,50 @@ func BuildStatSummaryRequest(p StatSummaryRequestParams) (*pb.StatSummaryRequest
|
||||||
TimeWindow: window,
|
TimeWindow: window,
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.OutToName != "" || p.OutToType != "" || p.OutToNamespace != "" {
|
if p.ToName != "" || p.ToType != "" || p.ToNamespace != "" {
|
||||||
if p.OutToNamespace == "" {
|
if p.ToNamespace == "" {
|
||||||
p.OutToNamespace = p.Namespace
|
p.ToNamespace = p.Namespace
|
||||||
|
}
|
||||||
|
if p.ToType == "" {
|
||||||
|
p.ToType = resourceType
|
||||||
}
|
}
|
||||||
|
|
||||||
outToResource := pb.StatSummaryRequest_OutToResource{
|
toType, err := k8s.CanonicalKubernetesNameFromFriendlyName(p.ToType)
|
||||||
OutToResource: &pb.Resource{
|
if err != nil {
|
||||||
Namespace: p.OutToNamespace,
|
return nil, err
|
||||||
Type: p.OutToType,
|
}
|
||||||
Name: p.OutToName,
|
|
||||||
|
toResource := pb.StatSummaryRequest_ToResource{
|
||||||
|
ToResource: &pb.Resource{
|
||||||
|
Namespace: p.ToNamespace,
|
||||||
|
Type: toType,
|
||||||
|
Name: p.ToName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
statRequest.Outbound = &outToResource
|
statRequest.Outbound = &toResource
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.OutFromName != "" || p.OutFromType != "" || p.OutFromNamespace != "" {
|
if p.FromName != "" || p.FromType != "" || p.FromNamespace != "" {
|
||||||
if p.OutFromNamespace == "" {
|
if p.FromNamespace == "" {
|
||||||
p.OutFromNamespace = p.Namespace
|
p.FromNamespace = p.Namespace
|
||||||
|
}
|
||||||
|
if p.FromType == "" {
|
||||||
|
p.FromType = resourceType
|
||||||
}
|
}
|
||||||
|
|
||||||
outFromResource := pb.StatSummaryRequest_OutFromResource{
|
fromType, err := k8s.CanonicalKubernetesNameFromFriendlyName(p.FromType)
|
||||||
OutFromResource: &pb.Resource{
|
if err != nil {
|
||||||
Namespace: p.OutFromNamespace,
|
return nil, err
|
||||||
Type: p.OutFromType,
|
}
|
||||||
Name: p.OutFromName,
|
|
||||||
|
fromResource := pb.StatSummaryRequest_FromResource{
|
||||||
|
FromResource: &pb.Resource{
|
||||||
|
Namespace: p.FromNamespace,
|
||||||
|
Type: fromType,
|
||||||
|
Name: p.FromName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
statRequest.Outbound = &outFromResource
|
statRequest.Outbound = &fromResource
|
||||||
}
|
}
|
||||||
|
|
||||||
return statRequest, nil
|
return statRequest, nil
|
||||||
|
|
|
@ -57,6 +57,9 @@ func main() {
|
||||||
|
|
||||||
sharedInformers := informers.NewSharedInformerFactory(k8sClient, 10*time.Minute)
|
sharedInformers := informers.NewSharedInformerFactory(k8sClient, 10*time.Minute)
|
||||||
|
|
||||||
|
namespaceInformer := sharedInformers.Core().V1().Namespaces()
|
||||||
|
namespaceInformerSynced := namespaceInformer.Informer().HasSynced
|
||||||
|
|
||||||
deployInformer := sharedInformers.Apps().V1beta2().Deployments()
|
deployInformer := sharedInformers.Apps().V1beta2().Deployments()
|
||||||
deployInformerSynced := deployInformer.Informer().HasSynced
|
deployInformerSynced := deployInformer.Informer().HasSynced
|
||||||
|
|
||||||
|
@ -77,6 +80,7 @@ func main() {
|
||||||
*addr,
|
*addr,
|
||||||
prometheusClient,
|
prometheusClient,
|
||||||
tapClient,
|
tapClient,
|
||||||
|
namespaceInformer.Lister(),
|
||||||
deployInformer.Lister(),
|
deployInformer.Lister(),
|
||||||
replicaSetInformer.Lister(),
|
replicaSetInformer.Lister(),
|
||||||
podInformer.Lister(),
|
podInformer.Lister(),
|
||||||
|
@ -91,6 +95,7 @@ func main() {
|
||||||
log.Infof("waiting for caches to sync")
|
log.Infof("waiting for caches to sync")
|
||||||
if !cache.WaitForCacheSync(
|
if !cache.WaitForCacheSync(
|
||||||
ctx.Done(),
|
ctx.Done(),
|
||||||
|
namespaceInformerSynced,
|
||||||
deployInformerSynced,
|
deployInformerSynced,
|
||||||
replicaSetInformerSynced,
|
replicaSetInformerSynced,
|
||||||
podInformerSynced,
|
podInformerSynced,
|
||||||
|
|
|
@ -487,8 +487,8 @@ type StatSummaryRequest struct {
|
||||||
TimeWindow TimeWindow `protobuf:"varint,2,opt,name=time_window,json=timeWindow,enum=conduit.public.TimeWindow" json:"time_window,omitempty"`
|
TimeWindow TimeWindow `protobuf:"varint,2,opt,name=time_window,json=timeWindow,enum=conduit.public.TimeWindow" json:"time_window,omitempty"`
|
||||||
// Types that are valid to be assigned to Outbound:
|
// Types that are valid to be assigned to Outbound:
|
||||||
// *StatSummaryRequest_None
|
// *StatSummaryRequest_None
|
||||||
// *StatSummaryRequest_OutToResource
|
// *StatSummaryRequest_ToResource
|
||||||
// *StatSummaryRequest_OutFromResource
|
// *StatSummaryRequest_FromResource
|
||||||
Outbound isStatSummaryRequest_Outbound `protobuf_oneof:"outbound"`
|
Outbound isStatSummaryRequest_Outbound `protobuf_oneof:"outbound"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,16 +502,16 @@ type isStatSummaryRequest_Outbound interface{ isStatSummaryRequest_Outbound() }
|
||||||
type StatSummaryRequest_None struct {
|
type StatSummaryRequest_None struct {
|
||||||
None *Empty `protobuf:"bytes,3,opt,name=none,oneof"`
|
None *Empty `protobuf:"bytes,3,opt,name=none,oneof"`
|
||||||
}
|
}
|
||||||
type StatSummaryRequest_OutToResource struct {
|
type StatSummaryRequest_ToResource struct {
|
||||||
OutToResource *Resource `protobuf:"bytes,4,opt,name=out_to_resource,json=outToResource,oneof"`
|
ToResource *Resource `protobuf:"bytes,4,opt,name=to_resource,json=toResource,oneof"`
|
||||||
}
|
}
|
||||||
type StatSummaryRequest_OutFromResource struct {
|
type StatSummaryRequest_FromResource struct {
|
||||||
OutFromResource *Resource `protobuf:"bytes,5,opt,name=out_from_resource,json=outFromResource,oneof"`
|
FromResource *Resource `protobuf:"bytes,5,opt,name=from_resource,json=fromResource,oneof"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*StatSummaryRequest_None) isStatSummaryRequest_Outbound() {}
|
func (*StatSummaryRequest_None) isStatSummaryRequest_Outbound() {}
|
||||||
func (*StatSummaryRequest_OutToResource) isStatSummaryRequest_Outbound() {}
|
func (*StatSummaryRequest_ToResource) isStatSummaryRequest_Outbound() {}
|
||||||
func (*StatSummaryRequest_OutFromResource) isStatSummaryRequest_Outbound() {}
|
func (*StatSummaryRequest_FromResource) isStatSummaryRequest_Outbound() {}
|
||||||
|
|
||||||
func (m *StatSummaryRequest) GetOutbound() isStatSummaryRequest_Outbound {
|
func (m *StatSummaryRequest) GetOutbound() isStatSummaryRequest_Outbound {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -541,16 +541,16 @@ func (m *StatSummaryRequest) GetNone() *Empty {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *StatSummaryRequest) GetOutToResource() *Resource {
|
func (m *StatSummaryRequest) GetToResource() *Resource {
|
||||||
if x, ok := m.GetOutbound().(*StatSummaryRequest_OutToResource); ok {
|
if x, ok := m.GetOutbound().(*StatSummaryRequest_ToResource); ok {
|
||||||
return x.OutToResource
|
return x.ToResource
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *StatSummaryRequest) GetOutFromResource() *Resource {
|
func (m *StatSummaryRequest) GetFromResource() *Resource {
|
||||||
if x, ok := m.GetOutbound().(*StatSummaryRequest_OutFromResource); ok {
|
if x, ok := m.GetOutbound().(*StatSummaryRequest_FromResource); ok {
|
||||||
return x.OutFromResource
|
return x.FromResource
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -559,8 +559,8 @@ func (m *StatSummaryRequest) GetOutFromResource() *Resource {
|
||||||
func (*StatSummaryRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
|
func (*StatSummaryRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
|
||||||
return _StatSummaryRequest_OneofMarshaler, _StatSummaryRequest_OneofUnmarshaler, _StatSummaryRequest_OneofSizer, []interface{}{
|
return _StatSummaryRequest_OneofMarshaler, _StatSummaryRequest_OneofUnmarshaler, _StatSummaryRequest_OneofSizer, []interface{}{
|
||||||
(*StatSummaryRequest_None)(nil),
|
(*StatSummaryRequest_None)(nil),
|
||||||
(*StatSummaryRequest_OutToResource)(nil),
|
(*StatSummaryRequest_ToResource)(nil),
|
||||||
(*StatSummaryRequest_OutFromResource)(nil),
|
(*StatSummaryRequest_FromResource)(nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,14 +573,14 @@ func _StatSummaryRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) erro
|
||||||
if err := b.EncodeMessage(x.None); err != nil {
|
if err := b.EncodeMessage(x.None); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case *StatSummaryRequest_OutToResource:
|
case *StatSummaryRequest_ToResource:
|
||||||
b.EncodeVarint(4<<3 | proto.WireBytes)
|
b.EncodeVarint(4<<3 | proto.WireBytes)
|
||||||
if err := b.EncodeMessage(x.OutToResource); err != nil {
|
if err := b.EncodeMessage(x.ToResource); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case *StatSummaryRequest_OutFromResource:
|
case *StatSummaryRequest_FromResource:
|
||||||
b.EncodeVarint(5<<3 | proto.WireBytes)
|
b.EncodeVarint(5<<3 | proto.WireBytes)
|
||||||
if err := b.EncodeMessage(x.OutFromResource); err != nil {
|
if err := b.EncodeMessage(x.FromResource); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case nil:
|
case nil:
|
||||||
|
@ -601,21 +601,21 @@ func _StatSummaryRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *p
|
||||||
err := b.DecodeMessage(msg)
|
err := b.DecodeMessage(msg)
|
||||||
m.Outbound = &StatSummaryRequest_None{msg}
|
m.Outbound = &StatSummaryRequest_None{msg}
|
||||||
return true, err
|
return true, err
|
||||||
case 4: // outbound.out_to_resource
|
case 4: // outbound.to_resource
|
||||||
if wire != proto.WireBytes {
|
if wire != proto.WireBytes {
|
||||||
return true, proto.ErrInternalBadWireType
|
return true, proto.ErrInternalBadWireType
|
||||||
}
|
}
|
||||||
msg := new(Resource)
|
msg := new(Resource)
|
||||||
err := b.DecodeMessage(msg)
|
err := b.DecodeMessage(msg)
|
||||||
m.Outbound = &StatSummaryRequest_OutToResource{msg}
|
m.Outbound = &StatSummaryRequest_ToResource{msg}
|
||||||
return true, err
|
return true, err
|
||||||
case 5: // outbound.out_from_resource
|
case 5: // outbound.from_resource
|
||||||
if wire != proto.WireBytes {
|
if wire != proto.WireBytes {
|
||||||
return true, proto.ErrInternalBadWireType
|
return true, proto.ErrInternalBadWireType
|
||||||
}
|
}
|
||||||
msg := new(Resource)
|
msg := new(Resource)
|
||||||
err := b.DecodeMessage(msg)
|
err := b.DecodeMessage(msg)
|
||||||
m.Outbound = &StatSummaryRequest_OutFromResource{msg}
|
m.Outbound = &StatSummaryRequest_FromResource{msg}
|
||||||
return true, err
|
return true, err
|
||||||
default:
|
default:
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -631,13 +631,13 @@ func _StatSummaryRequest_OneofSizer(msg proto.Message) (n int) {
|
||||||
n += proto.SizeVarint(3<<3 | proto.WireBytes)
|
n += proto.SizeVarint(3<<3 | proto.WireBytes)
|
||||||
n += proto.SizeVarint(uint64(s))
|
n += proto.SizeVarint(uint64(s))
|
||||||
n += s
|
n += s
|
||||||
case *StatSummaryRequest_OutToResource:
|
case *StatSummaryRequest_ToResource:
|
||||||
s := proto.Size(x.OutToResource)
|
s := proto.Size(x.ToResource)
|
||||||
n += proto.SizeVarint(4<<3 | proto.WireBytes)
|
n += proto.SizeVarint(4<<3 | proto.WireBytes)
|
||||||
n += proto.SizeVarint(uint64(s))
|
n += proto.SizeVarint(uint64(s))
|
||||||
n += s
|
n += s
|
||||||
case *StatSummaryRequest_OutFromResource:
|
case *StatSummaryRequest_FromResource:
|
||||||
s := proto.Size(x.OutFromResource)
|
s := proto.Size(x.FromResource)
|
||||||
n += proto.SizeVarint(5<<3 | proto.WireBytes)
|
n += proto.SizeVarint(5<<3 | proto.WireBytes)
|
||||||
n += proto.SizeVarint(uint64(s))
|
n += proto.SizeVarint(uint64(s))
|
||||||
n += s
|
n += s
|
||||||
|
@ -1238,81 +1238,80 @@ var _Api_serviceDesc = grpc.ServiceDesc{
|
||||||
func init() { proto.RegisterFile("public/api.proto", fileDescriptor0) }
|
func init() { proto.RegisterFile("public/api.proto", fileDescriptor0) }
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor0 = []byte{
|
||||||
// 1204 bytes of a gzipped FileDescriptorProto
|
// 1189 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x5d, 0x6f, 0x1b, 0x45,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x6e, 0x1b, 0xc5,
|
||||||
0x17, 0xb6, 0xd7, 0x4e, 0xb2, 0x3e, 0x8e, 0xd3, 0x74, 0xf2, 0xbe, 0x68, 0x6b, 0xa0, 0x32, 0xdb,
|
0x17, 0xb7, 0xd7, 0x4e, 0xb2, 0x3e, 0x8e, 0xd3, 0xfc, 0x27, 0x7f, 0xd0, 0xd6, 0x40, 0x65, 0xb6,
|
||||||
0x12, 0x22, 0x3e, 0x9c, 0xc8, 0x10, 0x89, 0xb4, 0x42, 0x90, 0xa4, 0x2e, 0x8e, 0xd4, 0x26, 0xd6,
|
0x25, 0x44, 0x7c, 0x38, 0x91, 0x21, 0x12, 0x69, 0x85, 0x4a, 0x92, 0x5a, 0x24, 0x52, 0x9b, 0x58,
|
||||||
0xc4, 0x7c, 0x48, 0x5c, 0x58, 0xe3, 0xdd, 0x49, 0xbc, 0x64, 0x77, 0x67, 0xba, 0x33, 0x4b, 0xc8,
|
0x93, 0xf0, 0x21, 0x71, 0x61, 0x8d, 0x77, 0x27, 0xf1, 0x92, 0xdd, 0x9d, 0xe9, 0xce, 0x2c, 0x21,
|
||||||
0xff, 0xe0, 0x82, 0x3b, 0xee, 0xf8, 0x27, 0x48, 0xfc, 0x00, 0xf8, 0x37, 0x5c, 0xa0, 0xf9, 0xd8,
|
0xef, 0xc1, 0x05, 0x77, 0xdc, 0xf1, 0x26, 0x08, 0x1e, 0x80, 0xc7, 0xe1, 0x02, 0xcd, 0xc7, 0x6e,
|
||||||
0x8d, 0xe3, 0x24, 0x6d, 0x55, 0xae, 0x3c, 0xe7, 0x39, 0xcf, 0x9c, 0x39, 0xe7, 0x39, 0x67, 0xd6,
|
0xec, 0x6d, 0xd2, 0x56, 0xe5, 0xca, 0xe7, 0xfc, 0xce, 0xef, 0x9c, 0x39, 0x5f, 0xb3, 0x1e, 0x58,
|
||||||
0x03, 0xab, 0x3c, 0x9f, 0xc4, 0x51, 0xb0, 0x49, 0x78, 0xd4, 0xe5, 0x19, 0x93, 0x0c, 0xad, 0x04,
|
0xe5, 0xf9, 0x24, 0x8e, 0x82, 0x4d, 0xc2, 0xa3, 0x3e, 0xcf, 0x98, 0x64, 0x68, 0x25, 0x60, 0x69,
|
||||||
0x2c, 0x0d, 0xf3, 0x48, 0x76, 0x8d, 0xa7, 0x7d, 0xff, 0x94, 0xb1, 0xd3, 0x98, 0x6e, 0x6a, 0xef,
|
0x98, 0x47, 0xb2, 0x6f, 0x2c, 0xdd, 0x7b, 0xe7, 0x8c, 0x9d, 0xc7, 0x74, 0x53, 0x5b, 0x27, 0xf9,
|
||||||
0x24, 0x3f, 0xd9, 0x0c, 0xf3, 0x8c, 0xc8, 0x88, 0xa5, 0x86, 0xdf, 0x5e, 0x0b, 0x58, 0x92, 0xb0,
|
0xd9, 0x66, 0x98, 0x67, 0x44, 0x46, 0x2c, 0x35, 0xfc, 0xee, 0x5a, 0xc0, 0x92, 0x84, 0xa5, 0x9b,
|
||||||
0x74, 0xd3, 0xfc, 0x58, 0xf0, 0xa1, 0x05, 0xa7, 0x94, 0xc4, 0x72, 0x1a, 0x4c, 0x69, 0x70, 0x36,
|
0xe6, 0xc7, 0x82, 0x0f, 0x2c, 0x38, 0xa5, 0x24, 0x96, 0xd3, 0x60, 0x4a, 0x83, 0x8b, 0x59, 0xd9,
|
||||||
0xbb, 0x36, 0x2c, 0x7f, 0x09, 0x16, 0xfa, 0x09, 0x97, 0x17, 0xfe, 0x0b, 0x68, 0x7e, 0x4b, 0x33,
|
0xb0, 0xfc, 0x25, 0x58, 0x18, 0x26, 0x5c, 0x5e, 0xf9, 0xcf, 0xa1, 0xfd, 0x2d, 0xcd, 0x44, 0xc4,
|
||||||
0x11, 0xb1, 0xf4, 0x20, 0x3d, 0x61, 0xe8, 0x1d, 0x68, 0x9c, 0x32, 0x0b, 0x78, 0xd5, 0x4e, 0x75,
|
0xd2, 0xc3, 0xf4, 0x8c, 0xa1, 0x77, 0xa1, 0x75, 0xce, 0x2c, 0xe0, 0xd5, 0x7b, 0xf5, 0x8d, 0x16,
|
||||||
0xa3, 0x81, 0x2f, 0x01, 0xe5, 0x9d, 0xe4, 0x51, 0x1c, 0x3e, 0x21, 0x92, 0x7a, 0x8e, 0xf1, 0x96,
|
0xbe, 0x06, 0x94, 0x75, 0x92, 0x47, 0x71, 0xf8, 0x84, 0x48, 0xea, 0x39, 0xc6, 0x5a, 0x02, 0x68,
|
||||||
0x00, 0x5a, 0x87, 0x95, 0x8c, 0xc6, 0x94, 0x08, 0x5a, 0x04, 0xa8, 0x69, 0xca, 0x1c, 0xea, 0x3f,
|
0x1d, 0x56, 0x32, 0x1a, 0x53, 0x22, 0x68, 0x11, 0xa0, 0xa1, 0x29, 0x15, 0xd4, 0x7f, 0x04, 0xab,
|
||||||
0x86, 0xd5, 0x67, 0x91, 0x90, 0x43, 0x16, 0x0a, 0x4c, 0x05, 0x67, 0xa9, 0xa0, 0xe8, 0x03, 0xa8,
|
0x4f, 0x23, 0x21, 0x47, 0x2c, 0x14, 0x98, 0x0a, 0xce, 0x52, 0x41, 0xd1, 0x87, 0xd0, 0xe4, 0x2c,
|
||||||
0x73, 0x16, 0x0a, 0xaf, 0xda, 0xa9, 0x6d, 0x34, 0x7b, 0x6b, 0xdd, 0xab, 0x4a, 0x74, 0x87, 0x2c,
|
0x14, 0x5e, 0xbd, 0xd7, 0xd8, 0x68, 0x0f, 0xd6, 0xfa, 0xf3, 0x9d, 0xe8, 0x8f, 0x58, 0x88, 0x35,
|
||||||
0xc4, 0x9a, 0xe0, 0xff, 0xea, 0x40, 0x6d, 0xc8, 0x42, 0x84, 0xa0, 0x9e, 0x92, 0x84, 0xda, 0x1c,
|
0xc1, 0xff, 0xd5, 0x81, 0xc6, 0x88, 0x85, 0x08, 0x41, 0x33, 0x25, 0x09, 0xb5, 0x39, 0x6a, 0x19,
|
||||||
0xf5, 0x1a, 0xfd, 0x0f, 0x16, 0x38, 0x0b, 0x0f, 0x86, 0x36, 0x35, 0x63, 0xa0, 0xfb, 0x00, 0x21,
|
0xfd, 0x1f, 0x16, 0x38, 0x0b, 0x0f, 0x47, 0x36, 0x35, 0xa3, 0xa0, 0x7b, 0x00, 0x21, 0xe5, 0x31,
|
||||||
0xe5, 0x31, 0xbb, 0x48, 0x68, 0x2a, 0x6d, 0x4a, 0x33, 0x08, 0x7a, 0x0b, 0x16, 0x85, 0x24, 0x32,
|
0xbb, 0x4a, 0x68, 0x2a, 0x6d, 0x4a, 0x33, 0x08, 0x7a, 0x1b, 0x16, 0x85, 0x24, 0x32, 0x17, 0x5e,
|
||||||
0x17, 0x5e, 0x5d, 0xfb, 0xac, 0xa5, 0xa2, 0x91, 0x30, 0xa4, 0xa1, 0xb7, 0xd0, 0xa9, 0x6e, 0xb8,
|
0x53, 0xdb, 0xac, 0xa6, 0xa2, 0x91, 0x30, 0xa4, 0xa1, 0xb7, 0xd0, 0xab, 0x6f, 0xb8, 0xd8, 0x28,
|
||||||
0xd8, 0x18, 0x68, 0x1f, 0xee, 0x88, 0x28, 0x0d, 0xe8, 0x33, 0x22, 0x24, 0xa6, 0x9c, 0x65, 0xd2,
|
0x68, 0x1f, 0xee, 0x88, 0x28, 0x0d, 0xe8, 0x53, 0x22, 0x24, 0xa6, 0x9c, 0x65, 0xd2, 0x5b, 0xec,
|
||||||
0x5b, 0xec, 0x54, 0x37, 0x9a, 0xbd, 0x7b, 0x5d, 0xd3, 0xad, 0x6e, 0xd1, 0xad, 0xee, 0x13, 0xdb,
|
0xd5, 0x37, 0xda, 0x83, 0xbb, 0x7d, 0x33, 0xad, 0x7e, 0x31, 0xad, 0xfe, 0x13, 0x3b, 0x2d, 0x5c,
|
||||||
0x2d, 0x3c, 0xbf, 0x03, 0x6d, 0xc1, 0x5a, 0xc0, 0x52, 0x99, 0xb1, 0x38, 0xa6, 0xd9, 0x21, 0x49,
|
0xf5, 0x40, 0x5b, 0xb0, 0x16, 0xb0, 0x54, 0x66, 0x2c, 0x8e, 0x69, 0x76, 0x44, 0x12, 0x2a, 0x38,
|
||||||
0xa8, 0xe0, 0x24, 0xa0, 0xde, 0x92, 0x3e, 0xff, 0x26, 0x17, 0xf2, 0x61, 0xd9, 0xc2, 0xc3, 0x98,
|
0x09, 0xa8, 0xb7, 0xa4, 0xcf, 0xbf, 0xc9, 0x84, 0x7c, 0x58, 0xb6, 0xf0, 0x28, 0x26, 0x29, 0xf5,
|
||||||
0xa4, 0xd4, 0x73, 0x75, 0x4e, 0x57, 0x30, 0xff, 0x77, 0x07, 0x60, 0x44, 0x38, 0xa6, 0x2f, 0x72,
|
0x5c, 0x9d, 0xd3, 0x1c, 0xe6, 0xff, 0xee, 0x00, 0x9c, 0x12, 0x8e, 0xe9, 0xf3, 0x9c, 0x0a, 0x89,
|
||||||
0x2a, 0x24, 0x42, 0x50, 0xe3, 0x2c, 0x34, 0x02, 0x0d, 0x2a, 0x58, 0x19, 0xa8, 0x73, 0x45, 0x0b,
|
0x10, 0x34, 0x38, 0x0b, 0x4d, 0x83, 0x0e, 0x6a, 0x58, 0x29, 0xa8, 0x37, 0xd7, 0x0b, 0xc7, 0x9a,
|
||||||
0xc7, 0xba, 0xe6, 0xd4, 0x48, 0xc8, 0xcf, 0x98, 0x0b, 0xad, 0x94, 0x83, 0xad, 0xa5, 0x70, 0xc9,
|
0x2a, 0xdd, 0x48, 0xc8, 0xcf, 0x98, 0x0b, 0xdd, 0x29, 0x07, 0x5b, 0x4d, 0xe1, 0x92, 0x8d, 0x54,
|
||||||
0x86, 0xaa, 0x5c, 0xa5, 0x52, 0x0b, 0x5b, 0x4b, 0xf5, 0x41, 0xb2, 0x83, 0xa1, 0x16, 0xa9, 0x81,
|
0xb9, 0xaa, 0x4b, 0x1d, 0x6c, 0x35, 0x35, 0x07, 0xc9, 0x0e, 0x47, 0xba, 0x49, 0x2d, 0xac, 0x65,
|
||||||
0xf5, 0x1a, 0xb5, 0xc1, 0x3d, 0xc9, 0x58, 0x32, 0x2c, 0xc4, 0x69, 0xe1, 0xd2, 0x56, 0x71, 0xd4,
|
0xd4, 0x05, 0xf7, 0x2c, 0x63, 0xc9, 0xa8, 0x68, 0x4e, 0x07, 0x97, 0xba, 0x8a, 0xa3, 0xe4, 0xc3,
|
||||||
0xfa, 0x60, 0x68, 0xab, 0xb5, 0x96, 0xee, 0x42, 0x30, 0xa5, 0x89, 0x29, 0x4d, 0x75, 0x41, 0x5b,
|
0x91, 0xad, 0xd6, 0x6a, 0x7a, 0x0a, 0xc1, 0x94, 0x26, 0xa6, 0x34, 0x35, 0x05, 0xad, 0xe9, 0x7c,
|
||||||
0x3a, 0x1f, 0x2a, 0xa7, 0x2c, 0xf4, 0x1a, 0x06, 0x37, 0x96, 0x1a, 0x45, 0x92, 0xcb, 0x29, 0xcb,
|
0xa8, 0x9c, 0xb2, 0xd0, 0x6b, 0x19, 0xdc, 0x68, 0x6a, 0x15, 0x49, 0x2e, 0xa7, 0x2c, 0x8b, 0xe4,
|
||||||
0x22, 0x79, 0xe1, 0x81, 0x19, 0xc5, 0x12, 0x50, 0x59, 0x71, 0x22, 0xa7, 0x5e, 0xd3, 0x64, 0xa5,
|
0x95, 0x07, 0x66, 0x15, 0x4b, 0x40, 0x65, 0xc5, 0x89, 0x9c, 0x7a, 0x6d, 0x93, 0x95, 0x92, 0xf7,
|
||||||
0xd6, 0x7b, 0x2e, 0x2c, 0x4a, 0x92, 0x9d, 0x52, 0xe9, 0x77, 0xc0, 0xdd, 0xe5, 0x51, 0x3f, 0xcb,
|
0x5c, 0x58, 0x94, 0x24, 0x3b, 0xa7, 0xd2, 0xef, 0x81, 0xbb, 0xcb, 0xa3, 0x61, 0x96, 0xb1, 0x4c,
|
||||||
0x58, 0xa6, 0xba, 0x4c, 0xd5, 0xc2, 0x0e, 0x92, 0x31, 0xfc, 0x21, 0xb8, 0x98, 0x0a, 0x96, 0x67,
|
0x4d, 0x99, 0x2a, 0xc1, 0x2e, 0x92, 0x51, 0xfc, 0x11, 0xb8, 0x98, 0x0a, 0x96, 0x67, 0x01, 0x55,
|
||||||
0x01, 0x55, 0x27, 0xa5, 0x65, 0x8b, 0xec, 0x95, 0x28, 0x01, 0x5d, 0xff, 0x05, 0x2f, 0x6e, 0x83,
|
0x27, 0xa5, 0xe5, 0x88, 0xec, 0x95, 0x28, 0x01, 0x5d, 0xff, 0x15, 0x2f, 0x6e, 0x83, 0x96, 0xcb,
|
||||||
0x5e, 0x97, 0xb3, 0x59, 0xbb, 0x9c, 0x4d, 0x9f, 0xc3, 0xdd, 0x22, 0xe2, 0x31, 0x8d, 0x69, 0xa0,
|
0xdd, 0x6c, 0x5c, 0xef, 0xa6, 0xcf, 0xe1, 0x7f, 0x45, 0xc4, 0x13, 0x1a, 0xd3, 0x40, 0x2d, 0x06,
|
||||||
0x06, 0x03, 0x7d, 0x06, 0x6e, 0x66, 0x41, 0x1d, 0xb9, 0xd9, 0xf3, 0xe6, 0x27, 0xbf, 0xd8, 0x84,
|
0xfa, 0x1c, 0xdc, 0xcc, 0x82, 0x3a, 0x72, 0x7b, 0xe0, 0x55, 0x37, 0xbf, 0x70, 0xc2, 0x25, 0x13,
|
||||||
0x4b, 0x26, 0x7a, 0x1f, 0x56, 0x62, 0x32, 0xa1, 0xf1, 0x58, 0xe8, 0x40, 0x2c, 0xb3, 0x87, 0xb7,
|
0x7d, 0x00, 0x2b, 0x31, 0x99, 0xd0, 0x78, 0x2c, 0x74, 0x20, 0x96, 0xd9, 0xc3, 0x3b, 0x1a, 0x3d,
|
||||||
0x34, 0x7a, 0x6c, 0x41, 0xff, 0x07, 0x68, 0x15, 0x9b, 0x4d, 0xa9, 0x6f, 0x76, 0x5a, 0x29, 0x90,
|
0xb1, 0xa0, 0xff, 0x03, 0x74, 0x0a, 0x67, 0x53, 0xea, 0x9b, 0x9d, 0x56, 0x36, 0xc8, 0x99, 0x6d,
|
||||||
0x33, 0x2b, 0xd0, 0xdf, 0x0e, 0xa0, 0x63, 0x49, 0xe4, 0x71, 0x9e, 0x24, 0x24, 0xbb, 0x28, 0x66,
|
0xd0, 0x9f, 0x0e, 0xa0, 0x13, 0x49, 0xe4, 0x49, 0x9e, 0x24, 0x24, 0xbb, 0x2a, 0x76, 0xee, 0x4b,
|
||||||
0xee, 0x0b, 0x70, 0xcb, 0xa4, 0xcc, 0x11, 0xef, 0xdd, 0x76, 0x44, 0xa9, 0x02, 0x2e, 0xb7, 0xa0,
|
0x70, 0xcb, 0xa4, 0xcc, 0x11, 0xef, 0xdf, 0x76, 0x44, 0xd9, 0x05, 0x5c, 0xba, 0xa0, 0x47, 0xd0,
|
||||||
0xc7, 0xd0, 0x94, 0x51, 0x42, 0xc7, 0xe7, 0x51, 0x1a, 0xb2, 0x73, 0x7d, 0xe2, 0x4a, 0xaf, 0x3d,
|
0x96, 0x51, 0x42, 0xc7, 0x97, 0x51, 0x1a, 0xb2, 0x4b, 0x7d, 0xe2, 0xca, 0xa0, 0x5b, 0x8d, 0x70,
|
||||||
0x1f, 0x61, 0x14, 0x25, 0xf4, 0x3b, 0xcd, 0xc0, 0x20, 0xcb, 0x35, 0xfa, 0x08, 0xea, 0x29, 0x4b,
|
0x1a, 0x25, 0xf4, 0x3b, 0xcd, 0xc0, 0x20, 0x4b, 0x19, 0x7d, 0x0c, 0xcd, 0x94, 0xa5, 0xa6, 0xeb,
|
||||||
0x8d, 0xea, 0xcd, 0xde, 0xff, 0xe7, 0x77, 0xe9, 0xcf, 0xdd, 0xa0, 0x82, 0x35, 0x09, 0xed, 0xc1,
|
0xed, 0xc1, 0x5b, 0x55, 0x2f, 0xfd, 0xb9, 0x3b, 0xa8, 0x61, 0x4d, 0xd2, 0x27, 0xb1, 0x71, 0xd9,
|
||||||
0x1d, 0x96, 0xcb, 0xb1, 0x64, 0xe3, 0x52, 0x92, 0xfa, 0xcb, 0x25, 0x19, 0x54, 0x70, 0x8b, 0xe5,
|
0x8e, 0xe6, 0xcb, 0xdb, 0xa1, 0xee, 0x88, 0x64, 0xe5, 0x46, 0x3c, 0x86, 0x8e, 0xda, 0xda, 0x6b,
|
||||||
0x72, 0xc4, 0xca, 0xc1, 0x78, 0x0a, 0x77, 0x55, 0x0c, 0x35, 0xc0, 0x97, 0x51, 0x16, 0x5e, 0x19,
|
0xf7, 0x85, 0x57, 0xba, 0x2f, 0x2b, 0x87, 0x42, 0xdf, 0x03, 0x70, 0x59, 0x2e, 0x27, 0x2c, 0x4f,
|
||||||
0x45, 0x1d, 0xfc, 0x34, 0x63, 0x49, 0x01, 0xed, 0x01, 0xb8, 0x2c, 0x97, 0x13, 0x96, 0xa7, 0xa1,
|
0x43, 0xff, 0xef, 0x3a, 0xac, 0xcd, 0x75, 0xd2, 0x7e, 0x11, 0xbf, 0x00, 0x87, 0x5d, 0xd8, 0x26,
|
||||||
0xff, 0x57, 0x15, 0xd6, 0xae, 0xe8, 0x6a, 0xbf, 0x8f, 0x9f, 0x83, 0xc3, 0xce, 0xac, 0xa4, 0xeb,
|
0xae, 0x57, 0x23, 0xdf, 0xe0, 0xd0, 0x3f, 0xbe, 0x38, 0xa8, 0x61, 0x87, 0x5d, 0xa0, 0xed, 0xd9,
|
||||||
0xf3, 0xc1, 0x6f, 0xd8, 0xd0, 0x3d, 0x3a, 0x1b, 0x54, 0xb0, 0xc3, 0xce, 0xd0, 0xf6, 0x6c, 0xff,
|
0x89, 0xb5, 0x07, 0xef, 0xdd, 0x96, 0x96, 0xde, 0x8a, 0x83, 0x9a, 0x1d, 0x69, 0xf7, 0x2b, 0x70,
|
||||||
0x9a, 0xbd, 0x77, 0x6f, 0xcb, 0x4c, 0xcf, 0xc8, 0xa0, 0x62, 0x1b, 0xdc, 0xfe, 0x0a, 0x9c, 0xa3,
|
0x8e, 0x2f, 0xd0, 0x43, 0x68, 0xab, 0xef, 0xdf, 0x58, 0x92, 0x49, 0x4c, 0x8b, 0xef, 0xf1, 0xdd,
|
||||||
0x33, 0xf4, 0x08, 0x9a, 0xea, 0x6b, 0x38, 0x96, 0x64, 0x12, 0xd3, 0xe2, 0xeb, 0x7c, 0xef, 0xa6,
|
0x9b, 0xce, 0x3f, 0x55, 0x0c, 0x0c, 0xa2, 0x10, 0x85, 0x2a, 0x2b, 0xb3, 0xd9, 0xf8, 0x7f, 0xd5,
|
||||||
0xf3, 0x47, 0x8a, 0x81, 0x41, 0x14, 0x4b, 0xa1, 0xca, 0xca, 0x6c, 0x36, 0xfe, 0x9f, 0x55, 0x80,
|
0x01, 0xf6, 0x88, 0x88, 0x02, 0x45, 0x15, 0xe8, 0x3e, 0x74, 0x44, 0x1e, 0x04, 0x54, 0x88, 0x71,
|
||||||
0x3d, 0x22, 0xa2, 0x40, 0x51, 0x05, 0x7a, 0x00, 0x2d, 0x91, 0x07, 0x01, 0x15, 0x62, 0x1c, 0xb0,
|
0xc0, 0xf2, 0x54, 0xea, 0xc2, 0x9a, 0x78, 0xd9, 0x82, 0xfb, 0x0a, 0x53, 0xa4, 0x33, 0x12, 0xc5,
|
||||||
0x3c, 0x95, 0xba, 0xb0, 0x3a, 0x5e, 0xb6, 0xe0, 0xbe, 0xc2, 0x14, 0xe9, 0x84, 0x44, 0x71, 0x9e,
|
0x79, 0x46, 0x2d, 0xc9, 0x31, 0x24, 0x0b, 0x1a, 0xd2, 0x03, 0xb5, 0xfd, 0x92, 0xa6, 0xc1, 0xd5,
|
||||||
0x51, 0x4b, 0x72, 0x0c, 0xc9, 0x82, 0x86, 0xf4, 0x50, 0xdd, 0x05, 0x49, 0xd3, 0xe0, 0x62, 0x9c,
|
0x38, 0x11, 0x63, 0xbe, 0xbd, 0xa5, 0x07, 0xde, 0xc4, 0xcb, 0x16, 0x7d, 0x26, 0x46, 0xdb, 0x5b,
|
||||||
0x88, 0x31, 0xdf, 0xde, 0xd2, 0xed, 0xaf, 0xe3, 0x65, 0x8b, 0x3e, 0x17, 0xc3, 0xed, 0xad, 0x79,
|
0x55, 0xd6, 0xce, 0xb6, 0x1e, 0xf1, 0x1c, 0x6b, 0x67, 0xfb, 0x05, 0xd6, 0x8e, 0x9e, 0xe4, 0x3c,
|
||||||
0xd6, 0xce, 0xb6, 0x6e, 0xf6, 0x15, 0xd6, 0xce, 0xf6, 0x35, 0xd6, 0x8e, 0x6e, 0xe6, 0x55, 0xd6,
|
0x6b, 0xc7, 0xff, 0xad, 0x01, 0xad, 0xb2, 0x60, 0xb4, 0x0b, 0x2d, 0xce, 0xc2, 0xf1, 0x79, 0xc6,
|
||||||
0x8e, 0xff, 0x5b, 0x0d, 0x1a, 0x65, 0xc1, 0x68, 0x17, 0x1a, 0x9c, 0x85, 0xe3, 0xd3, 0x8c, 0xe5,
|
0x72, 0x6e, 0xc7, 0xe3, 0xdf, 0xda, 0x1e, 0xf5, 0xc7, 0xf5, 0xb5, 0x62, 0x1e, 0xd4, 0xb0, 0xcb,
|
||||||
0xdc, 0xb6, 0xc7, 0xbf, 0x55, 0x1e, 0xf5, 0x37, 0xf6, 0xb5, 0x62, 0x0e, 0x2a, 0xd8, 0xe5, 0x76,
|
0xad, 0xdc, 0xfd, 0xc3, 0x01, 0xb7, 0x30, 0xa0, 0x87, 0xd0, 0xcc, 0xd8, 0x65, 0xd1, 0xe9, 0xf5,
|
||||||
0xdd, 0xfe, 0xc3, 0x01, 0xb7, 0x70, 0xa0, 0x47, 0x50, 0xcf, 0xd8, 0x79, 0xa1, 0xf4, 0xfa, 0xab,
|
0x57, 0x87, 0xea, 0x63, 0x76, 0x89, 0xb5, 0x4f, 0xf7, 0x9f, 0x3a, 0x34, 0x30, 0xbb, 0x7c, 0xc3,
|
||||||
0x43, 0x75, 0x31, 0x3b, 0xc7, 0x7a, 0x4f, 0xfb, 0x9f, 0x2a, 0xd4, 0x30, 0x3b, 0x7f, 0xc3, 0x7b,
|
0x9b, 0xfd, 0x9f, 0x6e, 0xdb, 0x06, 0xac, 0x26, 0x54, 0x4c, 0x69, 0x38, 0x56, 0xdd, 0x30, 0xe3,
|
||||||
0xfe, 0x9f, 0xee, 0xde, 0x06, 0xac, 0x26, 0x54, 0x4c, 0x69, 0x38, 0x56, 0x6a, 0x98, 0x76, 0x99,
|
0x32, 0x83, 0x58, 0x31, 0xf8, 0x88, 0x85, 0x66, 0x60, 0xeb, 0x70, 0x47, 0x32, 0x49, 0xe2, 0x19,
|
||||||
0x46, 0xac, 0x18, 0x7c, 0xc8, 0x42, 0xd3, 0xb0, 0x75, 0xb8, 0x23, 0x99, 0x24, 0xf1, 0x0c, 0xd1,
|
0xa2, 0x99, 0x45, 0x47, 0xc3, 0x25, 0x6f, 0x0b, 0x16, 0xd4, 0x2e, 0x09, 0x7b, 0x9b, 0x5e, 0x48,
|
||||||
0xf4, 0xa2, 0xa5, 0xe1, 0x92, 0xb7, 0x05, 0x0b, 0x6a, 0x96, 0x84, 0xbd, 0x50, 0xd7, 0x12, 0xb9,
|
0xe4, 0x7a, 0x9b, 0xb0, 0x21, 0xee, 0x2d, 0xc1, 0x82, 0x5e, 0xd3, 0x8f, 0x76, 0x01, 0xae, 0xd3,
|
||||||
0x9c, 0x26, 0x6c, 0x88, 0x7b, 0x4b, 0xb0, 0xa0, 0xc7, 0xf4, 0xc3, 0x5d, 0x80, 0xcb, 0x34, 0x51,
|
0x44, 0x6d, 0x58, 0x3a, 0x1d, 0x1e, 0x8d, 0x4f, 0x86, 0xfb, 0xab, 0x35, 0xa5, 0x1c, 0x1f, 0x0d,
|
||||||
0x13, 0x96, 0x46, 0xfd, 0xc3, 0xf1, 0x71, 0x7f, 0x7f, 0xb5, 0xa2, 0x8c, 0xa3, 0xc3, 0xfe, 0xf8,
|
0xc7, 0xcf, 0x0e, 0x8f, 0x56, 0xeb, 0x85, 0x45, 0x29, 0x0e, 0x5a, 0x06, 0x57, 0x59, 0x0e, 0x8e,
|
||||||
0xf9, 0xc1, 0xe1, 0x6a, 0xb5, 0xf0, 0x28, 0xc3, 0x41, 0xcb, 0xe0, 0x2a, 0xcf, 0xe0, 0xe8, 0x1b,
|
0xbf, 0xc1, 0xab, 0x8d, 0xc1, 0x2f, 0x0d, 0x68, 0xec, 0xf2, 0x08, 0x7d, 0x0f, 0xed, 0x99, 0xcb,
|
||||||
0xbc, 0x5a, 0xeb, 0xfd, 0x52, 0x83, 0xda, 0x2e, 0x8f, 0xd0, 0xf7, 0xd0, 0x9c, 0xb9, 0x5c, 0xc8,
|
0x85, 0xfc, 0x97, 0xde, 0x3c, 0xfd, 0xd1, 0xeb, 0xde, 0x7f, 0x8d, 0xdb, 0xe9, 0xd7, 0xd0, 0x63,
|
||||||
0x7f, 0xe9, 0xcd, 0xd3, 0x9f, 0xc0, 0xf6, 0x83, 0xd7, 0xb8, 0x9d, 0x7e, 0x05, 0x7d, 0x09, 0x4b,
|
0x58, 0x2a, 0xde, 0x51, 0x37, 0x7f, 0x9c, 0xba, 0xef, 0x54, 0xe1, 0x99, 0x97, 0x99, 0x5f, 0x43,
|
||||||
0xc5, 0xab, 0xea, 0xe6, 0x4f, 0x55, 0xfb, 0xed, 0x79, 0x78, 0xe6, 0x9d, 0xe6, 0x57, 0x50, 0x1f,
|
0x43, 0x70, 0x8b, 0x77, 0xd3, 0x6d, 0x11, 0x7a, 0x55, 0xb8, 0xfa, 0xd0, 0xf2, 0x6b, 0xe8, 0x47,
|
||||||
0xdc, 0xe2, 0x15, 0x75, 0x5b, 0x84, 0xce, 0x3c, 0x3c, 0xff, 0xec, 0xf2, 0x2b, 0xe8, 0x47, 0x68,
|
0x68, 0x9d, 0xd0, 0xf8, 0x6c, 0x5f, 0xbd, 0x06, 0xd1, 0x27, 0xa5, 0x83, 0x7d, 0x44, 0xce, 0x3e,
|
||||||
0x1c, 0xd3, 0xf8, 0x64, 0x5f, 0xbd, 0x0d, 0xd1, 0xc7, 0xe5, 0x06, 0xfb, 0xa4, 0x9c, 0x7d, 0x38,
|
0x15, 0x4b, 0x5a, 0x51, 0xe9, 0xa7, 0xaf, 0xc9, 0x9e, 0xa9, 0xb9, 0x71, 0x4a, 0x38, 0x7a, 0x71,
|
||||||
0x96, 0xb4, 0xa2, 0xd2, 0x4f, 0x5e, 0x93, 0x3d, 0x53, 0x73, 0x6d, 0x44, 0x38, 0xba, 0x3e, 0x54,
|
0xa9, 0xca, 0x67, 0x4a, 0xd7, 0xab, 0xc6, 0x3c, 0x25, 0x7c, 0xf8, 0x13, 0x4d, 0xa5, 0x5f, 0xdb,
|
||||||
0xe5, 0xa3, 0xa5, 0xed, 0xcd, 0xc7, 0x1c, 0x11, 0xde, 0xff, 0x89, 0xa6, 0xd2, 0xaf, 0x6c, 0x55,
|
0xaa, 0x4f, 0x16, 0xf5, 0x6b, 0xea, 0xb3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x9d, 0x3d,
|
||||||
0x27, 0x8b, 0xfa, 0x6d, 0xf5, 0xe9, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x43, 0x1e, 0x96, 0xb2,
|
0xa9, 0x2d, 0x0b, 0x00, 0x00,
|
||||||
0x3b, 0x0b, 0x00, 0x00,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
KubernetesDeployments = "deployments"
|
KubernetesDeployments = "deployments"
|
||||||
|
KubernetesNamespaces = "namespaces"
|
||||||
KubernetesPods = "pods"
|
KubernetesPods = "pods"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -58,6 +59,8 @@ func CanonicalKubernetesNameFromFriendlyName(friendlyName string) (string, error
|
||||||
switch friendlyName {
|
switch friendlyName {
|
||||||
case "deploy", "deployment", "deployments":
|
case "deploy", "deployment", "deployments":
|
||||||
return KubernetesDeployments, nil
|
return KubernetesDeployments, nil
|
||||||
|
case "ns", "namespace", "namespaces":
|
||||||
|
return KubernetesNamespaces, nil
|
||||||
case "po", "pod", "pods":
|
case "po", "pod", "pods":
|
||||||
return KubernetesPods, nil
|
return KubernetesPods, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,8 +80,8 @@ message StatSummaryRequest {
|
||||||
|
|
||||||
oneof outbound {
|
oneof outbound {
|
||||||
Empty none = 3;
|
Empty none = 3;
|
||||||
Resource out_to_resource = 4;
|
Resource to_resource = 4;
|
||||||
Resource out_from_resource = 5;
|
Resource from_resource = 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,16 +71,16 @@ func (h *handler) handleApiPods(w http.ResponseWriter, req *http.Request, p http
|
||||||
|
|
||||||
func (h *handler) handleApiStat(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
|
func (h *handler) handleApiStat(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
|
||||||
requestParams := util.StatSummaryRequestParams{
|
requestParams := util.StatSummaryRequestParams{
|
||||||
TimeWindow: req.FormValue("window"),
|
TimeWindow: req.FormValue("window"),
|
||||||
ResourceName: req.FormValue("resource_name"),
|
ResourceName: req.FormValue("resource_name"),
|
||||||
ResourceType: req.FormValue("resource_type"),
|
ResourceType: req.FormValue("resource_type"),
|
||||||
Namespace: req.FormValue("namespace"),
|
Namespace: req.FormValue("namespace"),
|
||||||
OutToName: req.FormValue("out_to_name"),
|
ToName: req.FormValue("to_name"),
|
||||||
OutToType: req.FormValue("out_to_type"),
|
ToType: req.FormValue("to_type"),
|
||||||
OutToNamespace: req.FormValue("out_to_namespace"),
|
ToNamespace: req.FormValue("to_namespace"),
|
||||||
OutFromName: req.FormValue("out_from_name"),
|
FromName: req.FormValue("from_name"),
|
||||||
OutFromType: req.FormValue("out_from_type"),
|
FromType: req.FormValue("from_type"),
|
||||||
OutFromNamespace: req.FormValue("out_from_namespace"),
|
FromNamespace: req.FormValue("from_namespace"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// default to returning deployment stats
|
// default to returning deployment stats
|
||||||
|
|
Loading…
Reference in New Issue