2023-03-28 18:39:22 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
2023-08-11 13:12:13 +00:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
2023-03-28 18:39:22 +00:00
|
|
|
|
2023-02-08 20:07:21 +00:00
|
|
|
//go:build !consulent
|
|
|
|
// +build !consulent
|
|
|
|
|
|
|
|
package agent
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestOperator_Usage(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("too slow for testing.Short")
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Parallel()
|
|
|
|
a := NewTestAgent(t, "")
|
|
|
|
defer a.Shutdown()
|
|
|
|
req, err := http.NewRequest("GET", "/v1/operator/usage", nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Register a few services
|
|
|
|
require.NoError(t, upsertTestService(a.RPC, "", "dc1", "web", "test-node", "", func(svc *structs.NodeService) {
|
|
|
|
svc.ID = "web1"
|
|
|
|
}))
|
|
|
|
require.NoError(t, upsertTestService(a.RPC, "", "dc1", "web", "test-node", "", func(svc *structs.NodeService) {
|
|
|
|
svc.ID = "web2"
|
|
|
|
}))
|
|
|
|
require.NoError(t, upsertTestService(a.RPC, "", "dc1", "db", "test-node", ""))
|
|
|
|
require.NoError(t, upsertTestService(a.RPC, "", "dc1", "web-proxy", "test-node", "", func(svc *structs.NodeService) {
|
|
|
|
svc.Kind = structs.ServiceKindConnectProxy
|
|
|
|
svc.Proxy = structs.ConnectProxyConfig{
|
|
|
|
DestinationServiceName: "web",
|
|
|
|
DestinationServiceID: "web1",
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
|
|
|
|
// Add connect-native service to check that we include it in the billable service instances
|
|
|
|
require.NoError(t, upsertTestService(a.RPC, "", "dc1", "connect-native-app", "test-node", "", func(svc *structs.NodeService) {
|
|
|
|
svc.Connect.Native = true
|
|
|
|
}))
|
|
|
|
|
|
|
|
raw, err := a.srv.OperatorUsage(httptest.NewRecorder(), req)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
expected := map[string]structs.ServiceUsage{
|
|
|
|
"dc1": {
|
|
|
|
Services: 5,
|
|
|
|
ServiceInstances: 6,
|
|
|
|
ConnectServiceInstances: map[string]int{
|
2023-06-09 12:22:32 +00:00
|
|
|
"api-gateway": 0,
|
2023-02-08 20:07:21 +00:00
|
|
|
"connect-native": 1,
|
|
|
|
"connect-proxy": 1,
|
|
|
|
"ingress-gateway": 0,
|
|
|
|
"mesh-gateway": 0,
|
|
|
|
"terminating-gateway": 0,
|
|
|
|
},
|
|
|
|
// 4 = 6 total service instances - 1 connect proxy - 1 consul service
|
|
|
|
BillableServiceInstances: 4,
|
2023-07-05 15:23:29 +00:00
|
|
|
Nodes: 2,
|
2023-02-08 20:07:21 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
require.Equal(t, expected, raw.(structs.Usage).Usage)
|
|
|
|
}
|
|
|
|
|
|
|
|
func upsertTestService(rpc rpcFn, secret, datacenter, name, node, partition string, modifyFuncs ...func(*structs.NodeService)) error {
|
|
|
|
req := structs.RegisterRequest{
|
|
|
|
Datacenter: datacenter,
|
|
|
|
Node: node,
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
ID: name,
|
|
|
|
Service: name,
|
|
|
|
Port: 8080,
|
|
|
|
},
|
|
|
|
WriteRequest: structs.WriteRequest{Token: secret},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, modify := range modifyFuncs {
|
|
|
|
modify(req.Service)
|
|
|
|
}
|
|
|
|
|
|
|
|
var out struct{}
|
|
|
|
return rpc(context.Background(), "Catalog.Register", &req, &out)
|
|
|
|
}
|