Skip to content

Commit 82d037b

Browse files
committed
fix(grafana): resolve CI failures
- Add license header to grafana.lr (copywrite check) - Fix gofmt struct tag alignment in service_accounts.go - Extract fetchServiceAccountPage helper to avoid defer resp.Body.Close() inside pagination loop (FD leak on multi-page results)
1 parent fc4b6f2 commit 82d037b

File tree

2 files changed

+30
-15
lines changed

2 files changed

+30
-15
lines changed

providers/grafana/resources/grafana.lr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright (c) Mondoo, Inc.
2+
// SPDX-License-Identifier: BUSL-1.1
3+
14
option provider = "go.mondoo.com/mql/v13/providers/grafana"
25
option go_package = "go.mondoo.com/mql/v13/providers/grafana/resources"
36

providers/grafana/resources/service_accounts.go

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"strconv"
1212

1313
"go.mondoo.com/mql/v13/llx"
14+
"go.mondoo.com/mql/v13/providers/grafana/connection"
1415
)
1516

1617
// grafanaServiceAccountJSON mirrors one element of the /api/serviceaccounts/search response.
@@ -26,10 +27,10 @@ type grafanaServiceAccountJSON struct {
2627

2728
// grafanaServiceAccountsResponse wraps the paginated service accounts endpoint.
2829
type grafanaServiceAccountsResponse struct {
29-
TotalCount int `json:"totalCount"`
30-
ServiceAccounts []grafanaServiceAccountJSON `json:"serviceAccounts"`
31-
Page int `json:"page"`
32-
PerPage int `json:"perPage"`
30+
TotalCount int `json:"totalCount"`
31+
ServiceAccounts []grafanaServiceAccountJSON `json:"serviceAccounts"`
32+
Page int `json:"page"`
33+
PerPage int `json:"perPage"`
3334
}
3435

3536
// grafanaTokenJSON mirrors one element of the /api/serviceaccounts/{id}/tokens response.
@@ -45,6 +46,27 @@ type grafanaTokenJSON struct {
4546

4647
const serviceAccountPageSize = 1000
4748

49+
// fetchServiceAccountPage fetches a single page of service accounts and closes
50+
// the response body before returning, avoiding FD leaks in pagination loops.
51+
func fetchServiceAccountPage(conn *connection.GrafanaConnection, page int) (*grafanaServiceAccountsResponse, error) {
52+
path := fmt.Sprintf("/api/serviceaccounts/search?perpage=%d&page=%d", serviceAccountPageSize, page)
53+
resp, err := conn.Get(context.Background(), path)
54+
if err != nil {
55+
return nil, err
56+
}
57+
defer resp.Body.Close()
58+
59+
if resp.StatusCode != http.StatusOK {
60+
return nil, fmt.Errorf("grafana: GET /api/serviceaccounts/search returned status %d", resp.StatusCode)
61+
}
62+
63+
var result grafanaServiceAccountsResponse
64+
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
65+
return nil, fmt.Errorf("grafana: decoding /api/serviceaccounts/search response: %w", err)
66+
}
67+
return &result, nil
68+
}
69+
4870
func (g *mqlGrafana) serviceAccounts() ([]interface{}, error) {
4971
conn, err := grafanaConnection(g.MqlRuntime)
5072
if err != nil {
@@ -56,20 +78,10 @@ func (g *mqlGrafana) serviceAccounts() ([]interface{}, error) {
5678
// page returns fewer results than requested.
5779
var allSAs []grafanaServiceAccountJSON
5880
for page := 1; ; page++ {
59-
path := fmt.Sprintf("/api/serviceaccounts/search?perpage=%d&page=%d", serviceAccountPageSize, page)
60-
resp, err := conn.Get(context.Background(), path)
81+
result, err := fetchServiceAccountPage(conn, page)
6182
if err != nil {
6283
return nil, err
6384
}
64-
defer resp.Body.Close()
65-
if resp.StatusCode != http.StatusOK {
66-
return nil, fmt.Errorf("grafana: GET /api/serviceaccounts/search returned status %d", resp.StatusCode)
67-
}
68-
69-
var result grafanaServiceAccountsResponse
70-
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
71-
return nil, fmt.Errorf("grafana: decoding /api/serviceaccounts/search response: %w", err)
72-
}
7385

7486
allSAs = append(allSAs, result.ServiceAccounts...)
7587

0 commit comments

Comments
 (0)