Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .changelog/17939.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
```release-note:improvement
http: GET API `operator/usage` endpoint now returns node count
cli: `consul operator usage` command now returns node count
```
6 changes: 6 additions & 0 deletions agent/consul/state/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,11 @@ func (s *Store) ServiceUsage(ws memdb.WatchSet) (uint64, structs.ServiceUsage, e
return 0, structs.ServiceUsage{}, fmt.Errorf("failed services lookup: %s", err)
}

nodes, err := firstUsageEntry(ws, tx, tableNodes)
if err != nil {
return 0, structs.ServiceUsage{}, fmt.Errorf("failed nodes lookup: %s", err)
}

serviceKindInstances := make(map[string]int)
for _, kind := range allConnectKind {
usage, err := firstUsageEntry(ws, tx, connectUsageTableName(kind))
Expand All @@ -443,6 +448,7 @@ func (s *Store) ServiceUsage(ws memdb.WatchSet) (uint64, structs.ServiceUsage, e
Services: services.Count,
ConnectServiceInstances: serviceKindInstances,
BillableServiceInstances: billableServiceInstances.Count,
Nodes: nodes.Count,
}
results, err := compileEnterpriseServiceUsage(ws, tx, usage)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions agent/operator_endpoint_oss_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func TestOperator_Usage(t *testing.T) {
},
// 4 = 6 total service instances - 1 connect proxy - 1 consul service
BillableServiceInstances: 4,
Nodes: 2,
},
}
require.Equal(t, expected, raw.(structs.Usage).Usage)
Expand Down
1 change: 1 addition & 0 deletions agent/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2324,6 +2324,7 @@ type ServiceUsage struct {
ServiceInstances int
ConnectServiceInstances map[string]int
BillableServiceInstances int
Nodes int
EnterpriseServiceUsage
}

Expand Down
1 change: 1 addition & 0 deletions api/operator_usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type Usage struct {

// ServiceUsage contains information about the number of services and service instances for a datacenter.
type ServiceUsage struct {
Nodes int
Services int
ServiceInstances int
ConnectServiceInstances map[string]int
Expand Down
36 changes: 36 additions & 0 deletions command/operator/usage/instances/usage_instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ func (c *cmd) Run(args []string) int {
return 1
}
c.UI.Output(billableOutput + "\n")

c.UI.Output("\nNodes")
nodesOutput, err := formatNodesCounts(usage.Usage)
if err != nil {
c.UI.Error(err.Error())
return 1
}
c.UI.Output(nodesOutput + "\n\n")
}

// Output Connect service counts
Expand All @@ -115,6 +123,34 @@ func (c *cmd) Run(args []string) int {
return 0
}

func formatNodesCounts(usageStats map[string]api.ServiceUsage) (string, error) {
var output bytes.Buffer
tw := tabwriter.NewWriter(&output, 0, 2, 6, ' ', 0)

nodesTotal := 0

fmt.Fprintf(tw, "Datacenter\t")

fmt.Fprintf(tw, "Count\t")

fmt.Fprint(tw, "\t\n")

for dc, usage := range usageStats {
nodesTotal += usage.Nodes
fmt.Fprintf(tw, "%s\t%d\n", dc, usage.Nodes)
}

fmt.Fprint(tw, "\t\n")
fmt.Fprintf(tw, "Total")

fmt.Fprintf(tw, "\t%d", nodesTotal)

if err := tw.Flush(); err != nil {
return "", fmt.Errorf("Error flushing tabwriter: %s", err)
}
return strings.TrimSpace(output.String()), nil
}

func formatServiceCounts(usageStats map[string]api.ServiceUsage, billable, showDatacenter bool) (string, error) {
var output bytes.Buffer
tw := tabwriter.NewWriter(&output, 0, 2, 6, ' ', 0)
Expand Down
51 changes: 51 additions & 0 deletions command/operator/usage/instances/usage_instances_oss_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,54 @@ Total 45`,
})
}
}

func TestUsageInstances_formatNodesCounts(t *testing.T) {
usageBasic := map[string]api.ServiceUsage{
"dc1": {
Nodes: 10,
},
}

usageMultiDC := map[string]api.ServiceUsage{
"dc1": {
Nodes: 10,
},
"dc2": {
Nodes: 11,
},
}

cases := []struct {
name string
usageStats map[string]api.ServiceUsage
expectedNodes string
}{
{
name: "basic",
usageStats: usageBasic,
expectedNodes: `
Datacenter Count
dc1 10

Total 10`,
},
{
name: "multi-datacenter",
usageStats: usageMultiDC,
expectedNodes: `
Datacenter Count
dc1 10
dc2 11

Total 21`,
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
nodesOutput, err := formatNodesCounts(tc.usageStats)
require.NoError(t, err)
require.Equal(t, strings.TrimSpace(tc.expectedNodes), nodesOutput)
})
}
}
3 changes: 2 additions & 1 deletion website/content/api-docs/operator/usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ $ curl \
"mesh-gateway": 0,
"terminating-gateway": 0
},
"BillableServiceInstances": 0
"BillableServiceInstances": 0,
"Nodes": 1
}
},
"Index": 13,
Expand Down
13 changes: 13 additions & 0 deletions website/content/commands/operator/usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ Billable Services
Services Service instances
2 3

Nodes
Datacenter Count
dc1 1

Total 1

Connect Services
Type Service instances
connect-native 0
Expand All @@ -74,6 +80,13 @@ dc2 1 1

Total 3 4

Nodes
Datacenter Count
dc1 1
dc2 2

Total 3

Connect Services
Datacenter Type Service instances
dc1 connect-native 0
Expand Down