Skip to content

Commit

Permalink
Add NodeCount to telemetry data (#5147)
Browse files Browse the repository at this point in the history
  • Loading branch information
jjngx authored Feb 22, 2024
1 parent fdc3770 commit b4114ba
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 10 deletions.
6 changes: 6 additions & 0 deletions deployments/rbac/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ rules:
- get
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- apiGroups:
- ""
resources:
Expand Down
17 changes: 17 additions & 0 deletions internal/telemetry/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package telemetry

import (
"context"

metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// NodeCount returns the total number of nodes in the cluster.
// It returns an error if the underlying k8s API client errors.
func (c *Collector) NodeCount(ctx context.Context) (int, error) {
nodes, err := c.Config.K8sClientReader.CoreV1().Nodes().List(ctx, metaV1.ListOptions{})
if err != nil {
return 0, err
}
return len(nodes.Items), nil
}
94 changes: 94 additions & 0 deletions internal/telemetry/cluster_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package telemetry_test

import (
"context"
"testing"

"github.com/nginxinc/kubernetes-ingress/internal/telemetry"
apiCoreV1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
testClient "k8s.io/client-go/kubernetes/fake"
)

func TestNodeCountInAClusterWithThreeNodes(t *testing.T) {
t.Parallel()

c := newTestCollectorForCluserWithNodes(t, node1, node2, node3)

got, err := c.NodeCount(context.Background())
if err != nil {
t.Fatal(err)
}
want := 3
if want != got {
t.Errorf("want %v, got %v", want, got)
}
}

func TestNodeCountInAClusterWithOneNode(t *testing.T) {
t.Parallel()

c := newTestCollectorForCluserWithNodes(t, node1)
got, err := c.NodeCount(context.Background())
if err != nil {
t.Fatal(err)
}
want := 1
if want != got {
t.Errorf("want %v, got %v", want, got)
}
}

// newTestCollectorForClusterWithNodes returns a telemetry collector configured
// to simulate collecting data on a cluser with provided nodes.
func newTestCollectorForCluserWithNodes(t *testing.T, nodes ...runtime.Object) *telemetry.Collector {
t.Helper()

c, err := telemetry.NewCollector(
telemetry.CollectorConfig{},
)
if err != nil {
t.Fatal(err)
}
c.Config.K8sClientReader = testClient.NewSimpleClientset(nodes...)
return c
}

var (
node1 = &apiCoreV1.Node{
TypeMeta: metaV1.TypeMeta{
Kind: "Node",
APIVersion: "v1",
},
ObjectMeta: metaV1.ObjectMeta{
Name: "test-node-1",
Namespace: "default",
},
Spec: apiCoreV1.NodeSpec{},
}

node2 = &apiCoreV1.Node{
TypeMeta: metaV1.TypeMeta{
Kind: "Node",
APIVersion: "v1",
},
ObjectMeta: metaV1.ObjectMeta{
Name: "test-node-2",
Namespace: "default",
},
Spec: apiCoreV1.NodeSpec{},
}

node3 = &apiCoreV1.Node{
TypeMeta: metaV1.TypeMeta{
Kind: "Node",
APIVersion: "v1",
},
ObjectMeta: metaV1.ObjectMeta{
Name: "test-node-3",
Namespace: "default",
},
Spec: apiCoreV1.NodeSpec{},
}
)
10 changes: 7 additions & 3 deletions internal/telemetry/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ func (c *Collector) Start(ctx context.Context) {
// It exports data using provided exporter.
func (c *Collector) Collect(ctx context.Context) {
glog.V(3).Info("Collecting telemetry data")
// TODO: Re-add ctx to BuildReport when collecting Node Count.
data, err := c.BuildReport()
data, err := c.BuildReport(ctx)
if err != nil {
glog.Errorf("Error collecting telemetry data: %v", err)
}
Expand All @@ -92,13 +91,18 @@ func (c *Collector) Collect(ctx context.Context) {
}

// BuildReport takes context and builds report from gathered telemetry data.
func (c *Collector) BuildReport() (Data, error) {
func (c *Collector) BuildReport(ctx context.Context) (Data, error) {
d := Data{}
var err error

if c.Config.Configurator != nil {
d.NICResourceCounts.VirtualServers, d.NICResourceCounts.VirtualServerRoutes = c.Config.Configurator.GetVirtualServerCounts()
d.NICResourceCounts.TransportServers = c.Config.Configurator.GetTransportServerCounts()
}
nc, err := c.NodeCount(ctx)
if err != nil {
glog.Errorf("Error collecting telemetry data: Nodes: %v", err)
}
d.NodeCount = nc
return d, err
}
88 changes: 81 additions & 7 deletions internal/telemetry/collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/nginxinc/kubernetes-ingress/internal/telemetry"
conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
testClient "k8s.io/client-go/kubernetes/fake"
)

func TestCreateNewCollectorWithCustomReportingPeriod(t *testing.T) {
Expand Down Expand Up @@ -46,7 +47,8 @@ func TestCreateNewCollectorWithCustomExporter(t *testing.T) {
td := telemetry.Data{}

cfg := telemetry.CollectorConfig{
Configurator: newConfigurator(t),
K8sClientReader: testClient.NewSimpleClientset(),
Configurator: newConfigurator(t),
}

c, err := telemetry.NewCollector(cfg, telemetry.WithExporter(exp))
Expand All @@ -62,6 +64,76 @@ func TestCreateNewCollectorWithCustomExporter(t *testing.T) {
}
}

func TestCollectNodeCountInClusterWithOneNode(t *testing.T) {
t.Parallel()

buf := &bytes.Buffer{}
exp := &telemetry.StdoutExporter{Endpoint: buf}
cfg := telemetry.CollectorConfig{
Configurator: newConfigurator(t),
K8sClientReader: testClient.NewSimpleClientset(node1),
}

c, err := telemetry.NewCollector(cfg, telemetry.WithExporter(exp))
if err != nil {
t.Fatal(err)
}
c.Collect(context.Background())

td := telemetry.Data{
ProjectMeta: telemetry.ProjectMeta{
Name: "",
Version: "",
},
NICResourceCounts: telemetry.NICResourceCounts{
VirtualServers: 0,
VirtualServerRoutes: 0,
TransportServers: 0,
},
NodeCount: 1,
}
want := fmt.Sprintf("%+v", td)
got := buf.String()
if !cmp.Equal(want, got) {
t.Error(cmp.Diff(want, got))
}
}

func TestCollectNodeCountInClusterWithThreeNodes(t *testing.T) {
t.Parallel()

buf := &bytes.Buffer{}
exp := &telemetry.StdoutExporter{Endpoint: buf}
cfg := telemetry.CollectorConfig{
Configurator: newConfigurator(t),
K8sClientReader: testClient.NewSimpleClientset(node1, node2, node3),
}

c, err := telemetry.NewCollector(cfg, telemetry.WithExporter(exp))
if err != nil {
t.Fatal(err)
}
c.Collect(context.Background())

td := telemetry.Data{
ProjectMeta: telemetry.ProjectMeta{
Name: "",
Version: "",
},
NICResourceCounts: telemetry.NICResourceCounts{
VirtualServers: 0,
VirtualServerRoutes: 0,
TransportServers: 0,
},
NodeCount: 3,
}
want := fmt.Sprintf("%+v", td)
got := buf.String()
if !cmp.Equal(want, got) {
t.Error(cmp.Diff(want, got))
}
}

func TestCountVirtualServers(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -171,7 +243,8 @@ func TestCountVirtualServers(t *testing.T) {
configurator := newConfigurator(t)

c, err := telemetry.NewCollector(telemetry.CollectorConfig{
Configurator: configurator,
K8sClientReader: testClient.NewSimpleClientset(),
Configurator: configurator,
})
if err != nil {
t.Fatal(err)
Expand All @@ -184,7 +257,7 @@ func TestCountVirtualServers(t *testing.T) {
}
}

gotTraceDataOnAdd, err := c.BuildReport()
gotTraceDataOnAdd, err := c.BuildReport(context.Background())
if err != nil {
t.Fatal(err)
}
Expand All @@ -202,7 +275,7 @@ func TestCountVirtualServers(t *testing.T) {
}
}

gotTraceDataOnDelete, err := c.BuildReport()
gotTraceDataOnDelete, err := c.BuildReport(context.Background())
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -342,7 +415,8 @@ func TestCountTransportServers(t *testing.T) {
configurator := newConfigurator(t)

c, err := telemetry.NewCollector(telemetry.CollectorConfig{
Configurator: configurator,
K8sClientReader: testClient.NewSimpleClientset(),
Configurator: configurator,
})
if err != nil {
t.Fatal(err)
Expand All @@ -355,7 +429,7 @@ func TestCountTransportServers(t *testing.T) {
}
}

gotTraceDataOnAdd, err := c.BuildReport()
gotTraceDataOnAdd, err := c.BuildReport(context.Background())
if err != nil {
t.Fatal(err)
}
Expand All @@ -373,7 +447,7 @@ func TestCountTransportServers(t *testing.T) {
}
}

gotTraceDataOnDelete, err := c.BuildReport()
gotTraceDataOnDelete, err := c.BuildReport(context.Background())
if err != nil {
t.Fatal(err)
}
Expand Down
1 change: 1 addition & 0 deletions internal/telemetry/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func (e *StdoutExporter) Export(_ context.Context, data Data) error {
type Data struct {
ProjectMeta ProjectMeta
NICResourceCounts NICResourceCounts
NodeCount int
}

// ProjectMeta holds metadata for the project.
Expand Down

0 comments on commit b4114ba

Please sign in to comment.