Skip to content

Commit 4a16a7a

Browse files
committed
temp
1 parent db37d29 commit 4a16a7a

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
load("@io_bazel_rules_go//go:def.bzl", "go_test")
2+
3+
package(default_visibility = ["//enterprise:__subpackages__"])
4+
5+
go_test(
6+
name = "usage_test",
7+
srcs = ["usage_test.go"],
8+
deps = [
9+
"//enterprise/server/testutil/buildbuddy_enterprise",
10+
"//proto:api_key_go_proto",
11+
"//proto:capability_go_proto",
12+
"//proto:context_go_proto",
13+
"//proto:usage_go_proto",
14+
"//server/tables",
15+
"@com_github_stretchr_testify//assert",
16+
"@com_github_stretchr_testify//require",
17+
"@org_golang_google_protobuf//encoding/protojson",
18+
],
19+
)
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package usage_test
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
"testing"
9+
"time"
10+
11+
"github.com/buildbuddy-io/buildbuddy/enterprise/server/testutil/buildbuddy_enterprise"
12+
"github.com/buildbuddy-io/buildbuddy/server/tables"
13+
"github.com/stretchr/testify/assert"
14+
"github.com/stretchr/testify/require"
15+
"google.golang.org/protobuf/encoding/protojson"
16+
17+
akpb "github.com/buildbuddy-io/buildbuddy/proto/api_key"
18+
cappb "github.com/buildbuddy-io/buildbuddy/proto/capability"
19+
ctxpb "github.com/buildbuddy-io/buildbuddy/proto/context"
20+
usagepb "github.com/buildbuddy-io/buildbuddy/proto/usage"
21+
)
22+
23+
func TestGetUsage_ParentAdminFetchesChildGroupUsage(t *testing.T) {
24+
// Start enterprise app with usage tracking enabled.
25+
app := buildbuddy_enterprise.Run(t, "--app.usage_tracking_enabled=true", "--app.region=test")
26+
wc := buildbuddy_enterprise.LoginAsDefaultSelfAuthUser(t, app)
27+
28+
// Treat the logged-in user's selected group as the parent org; mark it as parent and
29+
// set SAML metadata so that authdb recognizes child orgs sharing the same IdP.
30+
parentGroupID := wc.RequestContext.GetGroupId()
31+
parent := &tables.Group{}
32+
require.NoError(t, app.DB().Where("group_id = ?", parentGroupID).Take(parent).Error)
33+
parent.IsParent = true
34+
parent.SamlIdpMetadataUrl = "https://idp.example.test/metadata"
35+
parent.URLIdentifier = "parent-org"
36+
require.NoError(t, app.DB().Save(parent).Error)
37+
38+
// Create a child group (same SAML as parent). Do NOT add the user as a member.
39+
child := &tables.Group{Name: "child-org", URLIdentifier: "child-org", SamlIdpMetadataUrl: parent.SamlIdpMetadataUrl}
40+
require.NoError(t, app.DB().Create(child).Error)
41+
42+
// Create an ORG_ADMIN API key for the parent org using cookie-authenticated Web RPC.
43+
createKeyReq := &akpb.CreateApiKeyRequest{
44+
RequestContext: &ctxpb.RequestContext{GroupId: parentGroupID},
45+
Label: "admin",
46+
Capability: []cappb.Capability{cappb.Capability_ORG_ADMIN},
47+
}
48+
createKeyRsp := &akpb.CreateApiKeyResponse{}
49+
require.NoError(t, wc.RPC("CreateApiKey", createKeyReq, createKeyRsp))
50+
adminAPIKey := createKeyRsp.GetApiKey().GetValue()
51+
require.NotEmpty(t, adminAPIKey)
52+
53+
// Seed a usage row for the child group.
54+
now := time.Now().UTC()
55+
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.UTC)
56+
periodStart := monthStart.Add(6 * time.Hour)
57+
seeded := &tables.Usage{
58+
GroupID: child.GroupID,
59+
PeriodStartUsec: periodStart.UnixMicro(),
60+
Region: "test",
61+
FinalBeforeUsec: periodStart.Add(time.Hour).UnixMicro(),
62+
UsageCounts: tables.UsageCounts{
63+
Invocations: 3,
64+
CASCacheHits: 1,
65+
ActionCacheHits: 2,
66+
TotalDownloadSizeBytes: 2048,
67+
LinuxExecutionDurationUsec: 111,
68+
TotalUploadSizeBytes: 4096,
69+
TotalCachedActionExecUsec: 222,
70+
CPUNanos: 333,
71+
},
72+
UsageLabels: tables.UsageLabels{Origin: "internal", Client: "bazel", Server: "app"},
73+
}
74+
db := app.DB()
75+
require.NoError(t, db.Create(seeded).Error)
76+
77+
// Make the HTTP protolet request using the parent admin API key and requesting the child group.
78+
// Use JSON body for documentation clarity.
79+
// Example curl:
80+
// curl -X GET \
81+
// -H "Content-Type: application/json" \
82+
// -H "x-buildbuddy-api-key: <PARENT_ADMIN_API_KEY>" \
83+
// --data '{"requestContext":{"groupId":"<CHILD_GROUP_ID>"}}' \
84+
// "http://localhost:8080/rpc/BuildBuddyService/GetUsage"
85+
// Example body for users:
86+
// {
87+
// "requestContext": {
88+
// "groupId": "<child-group-id>"
89+
// }
90+
// }
91+
jsonBody := fmt.Sprintf(`
92+
{
93+
"requestContext": {
94+
"group_id": "%s"
95+
}
96+
}`, child.GroupID)
97+
httpReq, err := http.NewRequest(http.MethodPost, app.HTTPURL()+"/rpc/BuildBuddyService/GetUsage", bytes.NewBufferString(jsonBody))
98+
require.NoError(t, err)
99+
httpReq.Header.Set("Content-Type", "application/json")
100+
httpReq.Header.Set("x-buildbuddy-api-key", adminAPIKey)
101+
102+
httpRes, err := http.DefaultClient.Do(httpReq)
103+
require.NoError(t, err)
104+
defer httpRes.Body.Close()
105+
resBytes, err := io.ReadAll(httpRes.Body)
106+
require.NoError(t, err)
107+
require.Equal(t, 200, httpRes.StatusCode)
108+
109+
rsp := &usagepb.GetUsageResponse{}
110+
require.NoError(t, protojson.Unmarshal(resBytes, rsp))
111+
112+
require.NotNil(t, rsp.GetUsage())
113+
assert.EqualValues(t, 3, rsp.GetUsage().GetInvocations())
114+
assert.EqualValues(t, 2, rsp.GetUsage().GetActionCacheHits())
115+
assert.EqualValues(t, 1, rsp.GetUsage().GetCasCacheHits())
116+
assert.EqualValues(t, 2048, rsp.GetUsage().GetTotalDownloadSizeBytes())
117+
assert.EqualValues(t, 4096, rsp.GetUsage().GetTotalUploadSizeBytes())
118+
assert.EqualValues(t, 111, rsp.GetUsage().GetLinuxExecutionDurationUsec())
119+
assert.EqualValues(t, 222, rsp.GetUsage().GetTotalCachedActionExecUsec())
120+
assert.EqualValues(t, 333, rsp.GetUsage().GetCloudCpuNanos())
121+
require.Len(t, rsp.GetDailyUsage(), 1)
122+
assert.EqualValues(t, 3, rsp.GetDailyUsage()[0].GetInvocations())
123+
}

0 commit comments

Comments
 (0)