Skip to content

Commit

Permalink
Add namespace as a resource type in public-api
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
siggy committed Apr 13, 2018
1 parent efdfc93 commit a0eac23
Show file tree
Hide file tree
Showing 13 changed files with 571 additions and 273 deletions.
97 changes: 63 additions & 34 deletions cli/cmd/stat_summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import (
"github.com/prometheus/common/log"
"github.com/runconduit/conduit/controller/api/util"
pb "github.com/runconduit/conduit/controller/gen/public"
"github.com/runconduit/conduit/pkg/k8s"
"github.com/spf13/cobra"
"k8s.io/api/core/v1"
)

var namespace, resourceType, resourceName string
var outToNamespace, outToType, outToName string
var outFromNamespace, outFromType, outFromName string
var toNamespace, toType, toName string
var fromNamespace, fromType, fromName string
var allNamespaces bool

var statSummaryCommand = &cobra.Command{
Expand All @@ -29,17 +30,24 @@ var statSummaryCommand = &cobra.Command{
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.
If no resource name is specified, displays stats about all resources of the specified RESOURCETYPE`,
Example: ` # Get all deployments in the test namespace.
conduit statsummary deployments -n test
# Get the hello1 deployment in the test namespace.
conduit statsummary deployments hello1 -n test`,
conduit statsummary deployments hello1 -n test
# Get the test namespace.
conduit statsummary namespaces test
# Get all namespaces.
conduit statsummary --all-namespaces=true namespaces`,
Args: cobra.RangeArgs(1, 2),
ValidArgs: []string{"deployment"},
ValidArgs: []string{k8s.KubernetesDeployments, k8s.KubernetesNamespaces},
RunE: func(cmd *cobra.Command, args []string) error {
switch len(args) {
case 1:
Expand Down Expand Up @@ -71,12 +79,12 @@ func init() {
RootCmd.AddCommand(statSummaryCommand)
statSummaryCommand.PersistentFlags().StringVarP(&namespace, "namespace", "n", "default", "Namespace of the specified resource")
statSummaryCommand.PersistentFlags().StringVarP(&timeWindow, "time-window", "t", "1m", "Stat window (one of: \"10s\", \"1m\", \"10m\", \"1h\")")
statSummaryCommand.PersistentFlags().StringVar(&outToName, "out-to", "", "If present, restricts outbound stats to the specified resource name")
statSummaryCommand.PersistentFlags().StringVar(&outToNamespace, "out-to-namespace", "", "Sets the namespace used to lookup the \"--out-to\" resource; by default the current \"--namespace\" is used")
statSummaryCommand.PersistentFlags().StringVar(&outToType, "out-to-resource", "", "If present, restricts outbound stats to the specified resource type")
statSummaryCommand.PersistentFlags().StringVar(&outFromName, "out-from", "", "If present, restricts outbound stats to the specified resource name")
statSummaryCommand.PersistentFlags().StringVar(&outFromNamespace, "out-from-namespace", "", "Sets the namespace used to lookup the \"--out-from\" resource; by default the current \"--namespace\" is used")
statSummaryCommand.PersistentFlags().StringVar(&outFromType, "out-from-resource", "", "If present, restricts outbound stats to the specified resource type")
statSummaryCommand.PersistentFlags().StringVar(&toName, "to", "", "If present, restricts outbound stats to the specified resource name")
statSummaryCommand.PersistentFlags().StringVar(&toNamespace, "to-namespace", "", "Sets the namespace used to lookup the \"--to\" resource; by default the current \"--namespace\" is used")
statSummaryCommand.PersistentFlags().StringVar(&toType, "to-resource", "", "Sets the resource type used to lookup the \"--to\" resource; by default the RESOURCETYPE is used")
statSummaryCommand.PersistentFlags().StringVar(&fromName, "from", "", "If present, restricts outbound stats from the specified resource name")
statSummaryCommand.PersistentFlags().StringVar(&fromNamespace, "from-namespace", "", "Sets the namespace used from lookup the \"--from\" resource; by default the current \"--namespace\" is used")
statSummaryCommand.PersistentFlags().StringVar(&fromType, "from-resource", "", "Sets the resource type used to lookup the \"--from\" resource; by default the RESOURCETYPE is used")
statSummaryCommand.PersistentFlags().BoolVar(&allNamespaces, "all-namespaces", false, "If present, returns stats across all namespaces, ignoring the \"--namespace\" flag")
}

Expand Down Expand Up @@ -109,15 +117,19 @@ func renderStatSummary(resp *pb.StatSummaryResponse) string {
return out
}

type summaryRow struct {
meshed string
type summaryRowStats struct {
requestRate float64
successRate float64
latencyP50 uint64
latencyP95 uint64
latencyP99 uint64
}

type summaryRow struct {
meshed string
*summaryRowStats
}

func writeStatTableToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
nameHeader := "NAME"
maxNameLength := len(nameHeader)
Expand Down Expand Up @@ -146,15 +158,22 @@ func writeStatTableToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
}

if r.Stats != nil {
stats[key].requestRate = getRequestRate(*r)
stats[key].successRate = getSuccessRate(*r)
stats[key].latencyP50 = r.Stats.LatencyMsP50
stats[key].latencyP95 = r.Stats.LatencyMsP95
stats[key].latencyP99 = r.Stats.LatencyMsP99
stats[key].summaryRowStats = &summaryRowStats{
requestRate: getRequestRate(*r),
successRate: getSuccessRate(*r),
latencyP50: r.Stats.LatencyMsP50,
latencyP95: r.Stats.LatencyMsP95,
latencyP99: r.Stats.LatencyMsP99,
}
}
}
}

if len(stats) == 0 {
fmt.Fprintln(w, "\tNo resources found.")
return
}

headers := make([]string, 0)
if allNamespaces {
headers = append(headers,
Expand All @@ -169,6 +188,7 @@ func writeStatTableToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
"LATENCY_P95",
"LATENCY_P99\t", // trailing \t is required to format last column
}...)

fmt.Fprintln(w, strings.Join(headers, "\t"))

sortedKeys := sortStatSummaryKeys(stats)
Expand All @@ -178,23 +198,32 @@ func writeStatTableToBuffer(resp *pb.StatSummaryResponse, w *tabwriter.Writer) {
name := parts[1]
values := make([]interface{}, 0)
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 {
values = append(values,
namespace+strings.Repeat(" ", maxNamespaceLength-len(namespace)))
templateString = "%s\t" + templateString
templateStringEmpty = "%s\t" + templateStringEmpty
}
values = append(values, []interface{}{
name + strings.Repeat(" ", maxNameLength-len(name)),
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].summaryRowStats != 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...)
}
}
}

Expand All @@ -207,16 +236,16 @@ func buildStatSummaryRequest() (*pb.StatSummaryRequest, error) {
}

requestParams := util.StatSummaryRequestParams{
TimeWindow: timeWindow,
ResourceName: resourceName,
ResourceType: resourceType,
Namespace: targetNamespace,
OutToName: outToName,
OutToType: outToType,
OutToNamespace: outToNamespace,
OutFromName: outFromName,
OutFromType: outFromType,
OutFromNamespace: outFromNamespace,
TimeWindow: timeWindow,
ResourceName: resourceName,
ResourceType: resourceType,
Namespace: targetNamespace,
ToName: toName,
ToType: toType,
ToNamespace: toNamespace,
FromName: fromName,
FromType: fromType,
FromNamespace: fromNamespace,
}

return util.BuildStatSummaryRequest(requestParams)
Expand Down
2 changes: 1 addition & 1 deletion controller/api/public/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,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 {
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)
if err != nil {
return err
Expand Down
3 changes: 3 additions & 0 deletions controller/api/public/grpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type (
prometheusAPI promv1.API
telemetryClient telemPb.TelemetryClient
tapClient tapPb.TapClient
namespaceLister corelisters.NamespaceLister
deployLister applisters.DeploymentLister
replicaSetLister applisters.ReplicaSetLister
podLister corelisters.PodLister
Expand Down Expand Up @@ -107,6 +108,7 @@ func newGrpcServer(
promAPI promv1.API,
telemetryClient telemPb.TelemetryClient,
tapClient tapPb.TapClient,
namespaceLister corelisters.NamespaceLister,
deployLister applisters.DeploymentLister,
replicaSetLister applisters.ReplicaSetLister,
podLister corelisters.PodLister,
Expand All @@ -117,6 +119,7 @@ func newGrpcServer(
prometheusAPI: promAPI,
telemetryClient: telemetryClient,
tapClient: tapClient,
namespaceLister: namespaceLister,
deployLister: deployLister,
replicaSetLister: replicaSetLister,
podLister: podLister,
Expand Down
4 changes: 4 additions & 0 deletions controller/api/public/grpc_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ func TestStat(t *testing.T) {
&MockProm{},
&mockTelemetry{test: t, tRes: tr.tRes, mReq: tr.mReq},
tap.NewTapClient(nil),
sharedInformers.Core().V1().Namespaces().Lister(),
sharedInformers.Apps().V1().Deployments().Lister(),
sharedInformers.Apps().V1().ReplicaSets().Lister(),
sharedInformers.Core().V1().Pods().Lister(),
Expand Down Expand Up @@ -411,6 +412,7 @@ spec:
clientSet := fake.NewSimpleClientset(k8sObjs...)
sharedInformers := informers.NewSharedInformerFactory(clientSet, 10*time.Minute)

namespaceInformer := sharedInformers.Core().V1().Namespaces()
deployInformer := sharedInformers.Apps().V1().Deployments()
replicaSetInformer := sharedInformers.Apps().V1().ReplicaSets()
podInformer := sharedInformers.Core().V1().Pods()
Expand All @@ -419,6 +421,7 @@ spec:
&MockProm{Res: exp.promRes},
&mockTelemetry{},
tap.NewTapClient(nil),
namespaceInformer.Lister(),
deployInformer.Lister(),
replicaSetInformer.Lister(),
podInformer.Lister(),
Expand All @@ -429,6 +432,7 @@ spec:
sharedInformers.Start(stopCh)
if !cache.WaitForCacheSync(
stopCh,
namespaceInformer.Informer().HasSynced,
deployInformer.Informer().HasSynced,
replicaSetInformer.Informer().HasSynced,
podInformer.Informer().HasSynced,
Expand Down
2 changes: 2 additions & 0 deletions controller/api/public/http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ func NewServer(
prometheusClient promApi.Client,
telemetryClient telemPb.TelemetryClient,
tapClient tapPb.TapClient,
namespaceLister corelisters.NamespaceLister,
deployLister applisters.DeploymentLister,
replicaSetLister applisters.ReplicaSetLister,
podLister corelisters.PodLister,
Expand All @@ -236,6 +237,7 @@ func NewServer(
promv1.NewAPI(prometheusClient),
telemetryClient,
tapClient,
namespaceLister,
deployLister,
replicaSetLister,
podLister,
Expand Down
Loading

0 comments on commit a0eac23

Please sign in to comment.