Skip to content

Commit 80da5bb

Browse files
Config Generation: Simplify listing of org resources
It's always the same pattern: Run a function for all orgs We can extract the "for each org" part to a common helper
1 parent 9631419 commit 80da5bb

14 files changed

+166
-250
lines changed

internal/resources/grafana/common_lister.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@ func (ld *ListerData) OrgIDs(client *goapi.GrafanaHTTPAPI) ([]int64, error) {
5454
return ld.orgIDs, nil
5555
}
5656

57+
type grafanaListerFunc func(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error)
58+
type grafanaOrgResourceListerFunc func(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error)
59+
5760
// listerFunction is a helper function that wraps a lister function be used more easily in grafana resources.
58-
func listerFunction(listerFunc func(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error)) common.ResourceListIDsFunc {
61+
func listerFunction(listerFunc grafanaListerFunc) common.ResourceListIDsFunc {
5962
return func(ctx context.Context, client *common.Client, data any) ([]string, error) {
6063
lm, ok := data.(*ListerData)
6164
if !ok {
@@ -67,3 +70,23 @@ func listerFunction(listerFunc func(ctx context.Context, client *goapi.GrafanaHT
6770
return listerFunc(ctx, client.GrafanaAPI, lm)
6871
}
6972
}
73+
74+
func listerFunctionOrgResource(listerFunc grafanaOrgResourceListerFunc) common.ResourceListIDsFunc {
75+
return listerFunction(func(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
76+
orgIDs, err := data.OrgIDs(client)
77+
if err != nil {
78+
return nil, err
79+
}
80+
81+
var ids []string
82+
for _, orgID := range orgIDs {
83+
idsInOrg, err := listerFunc(ctx, client.Clone().WithOrgID(orgID), orgID)
84+
if err != nil {
85+
return nil, err
86+
}
87+
ids = append(ids, idsInOrg...)
88+
}
89+
90+
return ids, nil
91+
})
92+
}

internal/resources/grafana/resource_alerting_message_template.go

+16-25
Original file line numberDiff line numberDiff line change
@@ -66,37 +66,28 @@ This resource requires Grafana 9.1.0 or later.
6666
"grafana_message_template",
6767
orgResourceIDString("name"),
6868
schema,
69-
).WithLister(listerFunction(listMessageTemplate))
69+
).WithLister(listerFunctionOrgResource(listMessageTemplate))
7070
}
7171

72-
func listMessageTemplate(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
73-
orgIDs, err := data.OrgIDs(client)
74-
if err != nil {
75-
return nil, err
76-
}
77-
72+
func listMessageTemplate(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error) {
7873
var ids []string
79-
for _, orgID := range orgIDs {
80-
client = client.Clone().WithOrgID(orgID)
81-
82-
// Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet.
83-
// The alertmanager is provisioned asynchronously when the org is created.
84-
if err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
85-
resp, err := client.Provisioning.GetTemplates()
86-
if err != nil {
87-
if orgID > 1 && (err.(*runtime.APIError).IsCode(500) || err.(*runtime.APIError).IsCode(403)) {
88-
return retry.RetryableError(err)
89-
}
90-
return retry.NonRetryableError(err)
74+
// Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet.
75+
// The alertmanager is provisioned asynchronously when the org is created.
76+
if err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
77+
resp, err := client.Provisioning.GetTemplates()
78+
if err != nil {
79+
if orgID > 1 && (err.(*runtime.APIError).IsCode(500) || err.(*runtime.APIError).IsCode(403)) {
80+
return retry.RetryableError(err)
9181
}
82+
return retry.NonRetryableError(err)
83+
}
9284

93-
for _, template := range resp.Payload {
94-
ids = append(ids, MakeOrgResourceID(orgID, template.Name))
95-
}
96-
return nil
97-
}); err != nil {
98-
return nil, err
85+
for _, template := range resp.Payload {
86+
ids = append(ids, MakeOrgResourceID(orgID, template.Name))
9987
}
88+
return nil
89+
}); err != nil {
90+
return nil, err
10091
}
10192

10293
return ids, nil

internal/resources/grafana/resource_alerting_mute_timing.go

+16-25
Original file line numberDiff line numberDiff line change
@@ -133,37 +133,28 @@ This resource requires Grafana 9.1.0 or later.
133133
"grafana_mute_timing",
134134
orgResourceIDString("name"),
135135
schema,
136-
).WithLister(listerFunction(listMuteTimings))
136+
).WithLister(listerFunctionOrgResource(listMuteTimings))
137137
}
138138

139-
func listMuteTimings(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
140-
orgIDs, err := data.OrgIDs(client)
141-
if err != nil {
142-
return nil, err
143-
}
144-
139+
func listMuteTimings(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error) {
145140
var ids []string
146-
for _, orgID := range orgIDs {
147-
client = client.Clone().WithOrgID(orgID)
148-
149-
// Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet.
150-
// The alertmanager is provisioned asynchronously when the org is created.
151-
if err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
152-
resp, err := client.Provisioning.GetMuteTimings()
153-
if err != nil {
154-
if orgID > 1 && (err.(*runtime.APIError).IsCode(500) || err.(*runtime.APIError).IsCode(403)) {
155-
return retry.RetryableError(err)
156-
}
157-
return retry.NonRetryableError(err)
141+
// Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet.
142+
// The alertmanager is provisioned asynchronously when the org is created.
143+
if err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
144+
resp, err := client.Provisioning.GetMuteTimings()
145+
if err != nil {
146+
if orgID > 1 && (err.(*runtime.APIError).IsCode(500) || err.(*runtime.APIError).IsCode(403)) {
147+
return retry.RetryableError(err)
158148
}
149+
return retry.NonRetryableError(err)
150+
}
159151

160-
for _, muteTiming := range resp.Payload {
161-
ids = append(ids, MakeOrgResourceID(orgID, muteTiming.Name))
162-
}
163-
return nil
164-
}); err != nil {
165-
return nil, err
152+
for _, muteTiming := range resp.Payload {
153+
ids = append(ids, MakeOrgResourceID(orgID, muteTiming.Name))
166154
}
155+
return nil
156+
}); err != nil {
157+
return nil, err
167158
}
168159

169160
return ids, nil

internal/resources/grafana/resource_alerting_notification_policy.go

+15-24
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ This resource requires Grafana 9.1.0 or later.
9191
"grafana_notification_policy",
9292
orgResourceIDString("anyString"),
9393
schema,
94-
).WithLister(listerFunction(listNotificationPolicies))
94+
).WithLister(listerFunctionOrgResource(listNotificationPolicies))
9595
}
9696

9797
// The maximum depth of policy tree that the provider supports, as Terraform does not allow for infinitely recursive schemas.
@@ -191,35 +191,26 @@ func policySchema(depth uint) *schema.Resource {
191191
return resource
192192
}
193193

194-
func listNotificationPolicies(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
195-
orgIDs, err := data.OrgIDs(client)
196-
if err != nil {
197-
return nil, err
198-
}
199-
194+
func listNotificationPolicies(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error) {
200195
var ids []string
201-
for _, orgID := range orgIDs {
202-
client = client.Clone().WithOrgID(orgID)
203-
204-
// Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet.
205-
// The alertmanager is provisioned asynchronously when the org is created.
206-
if err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
207-
_, err := client.Provisioning.GetPolicyTree()
208-
if err != nil {
209-
if orgID > 1 && (err.(*runtime.APIError).IsCode(500) || err.(*runtime.APIError).IsCode(403)) {
210-
return retry.RetryableError(err)
211-
}
212-
return retry.NonRetryableError(err)
196+
// Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet.
197+
// The alertmanager is provisioned asynchronously when the org is created.
198+
if err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
199+
_, err := client.Provisioning.GetPolicyTree()
200+
if err != nil {
201+
if orgID > 1 && (err.(*runtime.APIError).IsCode(500) || err.(*runtime.APIError).IsCode(403)) {
202+
return retry.RetryableError(err)
213203
}
214-
215-
return nil
216-
}); err != nil {
217-
return nil, err
204+
return retry.NonRetryableError(err)
218205
}
219206

220-
ids = append(ids, MakeOrgResourceID(orgID, PolicySingletonID))
207+
return nil
208+
}); err != nil {
209+
return nil, err
221210
}
222211

212+
ids = append(ids, MakeOrgResourceID(orgID, PolicySingletonID))
213+
223214
return ids, nil
224215
}
225216

internal/resources/grafana/resource_alerting_rule_group.go

+16-25
Original file line numberDiff line numberDiff line change
@@ -255,37 +255,28 @@ This resource requires Grafana 9.1.0 or later.
255255
"grafana_rule_group",
256256
resourceRuleGroupID,
257257
schema,
258-
).WithLister(listerFunction(listRuleGroups))
258+
).WithLister(listerFunctionOrgResource(listRuleGroups))
259259
}
260260

261-
func listRuleGroups(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
262-
orgIDs, err := data.OrgIDs(client)
263-
if err != nil {
264-
return nil, err
265-
}
266-
261+
func listRuleGroups(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error) {
267262
idMap := map[string]bool{}
268-
for _, orgID := range orgIDs {
269-
client = client.Clone().WithOrgID(orgID)
270-
271-
// Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet.
272-
// The alertmanager is provisioned asynchronously when the org is created.
273-
if err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
274-
resp, err := client.Provisioning.GetAlertRules()
275-
if err != nil {
276-
if orgID > 1 && (err.(*runtime.APIError).IsCode(500) || err.(*runtime.APIError).IsCode(403)) {
277-
return retry.RetryableError(err)
278-
}
279-
return retry.NonRetryableError(err)
263+
// Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet.
264+
// The alertmanager is provisioned asynchronously when the org is created.
265+
if err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
266+
resp, err := client.Provisioning.GetAlertRules()
267+
if err != nil {
268+
if orgID > 1 && (err.(*runtime.APIError).IsCode(500) || err.(*runtime.APIError).IsCode(403)) {
269+
return retry.RetryableError(err)
280270
}
271+
return retry.NonRetryableError(err)
272+
}
281273

282-
for _, rule := range resp.Payload {
283-
idMap[resourceRuleGroupID.Make(orgID, rule.FolderUID, rule.RuleGroup)] = true
284-
}
285-
return nil
286-
}); err != nil {
287-
return nil, err
274+
for _, rule := range resp.Payload {
275+
idMap[resourceRuleGroupID.Make(orgID, rule.FolderUID, rule.RuleGroup)] = true
288276
}
277+
return nil
278+
}); err != nil {
279+
return nil, err
289280
}
290281

291282
var ids []string

internal/resources/grafana/resource_annotation.go

+6-15
Original file line numberDiff line numberDiff line change
@@ -84,27 +84,18 @@ func resourceAnnotation() *common.Resource {
8484
"grafana_annotation",
8585
orgResourceIDInt("id"),
8686
schema,
87-
).WithLister(listerFunction(listAnnotations))
87+
).WithLister(listerFunctionOrgResource(listAnnotations))
8888
}
8989

90-
func listAnnotations(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
91-
orgIDs, err := data.OrgIDs(client)
90+
func listAnnotations(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error) {
91+
var ids []string
92+
resp, err := client.Annotations.GetAnnotations(annotations.NewGetAnnotationsParams())
9293
if err != nil {
9394
return nil, err
9495
}
9596

96-
var ids []string
97-
for _, orgID := range orgIDs {
98-
client = client.Clone().WithOrgID(orgID)
99-
100-
resp, err := client.Annotations.GetAnnotations(annotations.NewGetAnnotationsParams())
101-
if err != nil {
102-
return nil, err
103-
}
104-
105-
for _, annotation := range resp.Payload {
106-
ids = append(ids, MakeOrgResourceID(orgID, annotation.ID))
107-
}
97+
for _, annotation := range resp.Payload {
98+
ids = append(ids, MakeOrgResourceID(orgID, annotation.ID))
10899
}
109100

110101
return ids, nil

internal/resources/grafana/resource_dashboard.go

+8-17
Original file line numberDiff line numberDiff line change
@@ -99,31 +99,22 @@ Manages Grafana dashboards.
9999
"grafana_dashboard",
100100
orgResourceIDString("uid"),
101101
schema,
102-
).WithLister(listerFunction(listDashboards))
102+
).WithLister(listerFunctionOrgResource(listDashboards))
103103
}
104104

105-
func listDashboards(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
106-
return listDashboardOrFolder(client, data, "dash-db")
105+
func listDashboards(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error) {
106+
return listDashboardOrFolder(client, orgID, "dash-db")
107107
}
108108

109-
func listDashboardOrFolder(client *goapi.GrafanaHTTPAPI, data *ListerData, searchType string) ([]string, error) {
110-
orgIDs, err := data.OrgIDs(client)
109+
func listDashboardOrFolder(client *goapi.GrafanaHTTPAPI, orgID int64, searchType string) ([]string, error) {
110+
uids := []string{}
111+
resp, err := client.Search.Search(search.NewSearchParams().WithType(common.Ref(searchType)))
111112
if err != nil {
112113
return nil, err
113114
}
114115

115-
uids := []string{}
116-
for _, orgID := range orgIDs {
117-
client = client.Clone().WithOrgID(orgID)
118-
119-
resp, err := client.Search.Search(search.NewSearchParams().WithType(common.Ref(searchType)))
120-
if err != nil {
121-
return nil, err
122-
}
123-
124-
for _, item := range resp.Payload {
125-
uids = append(uids, MakeOrgResourceID(orgID, item.UID))
126-
}
116+
for _, item := range resp.Payload {
117+
uids = append(uids, MakeOrgResourceID(orgID, item.UID))
127118
}
128119

129120
return uids, nil

internal/resources/grafana/resource_data_source.go

+8-16
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ source selected (via the 'type' argument).
114114
"grafana_data_source",
115115
orgResourceIDString("uid"),
116116
schema,
117-
).WithLister(listerFunction(listDatasources))
117+
).WithLister(listerFunctionOrgResource(listDatasources))
118118
}
119119

120120
func datasourceHTTPHeadersAttribute() *schema.Schema {
@@ -182,26 +182,18 @@ func datasourceSecureJSONDataAttribute() *schema.Schema {
182182
}
183183
}
184184

185-
func listDatasources(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
186-
orgIDs, err := data.OrgIDs(client)
185+
func listDatasources(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error) {
186+
var ids []string
187+
resp, err := client.Datasources.GetDataSources()
187188
if err != nil {
188189
return nil, err
189190
}
190191

191-
var ids []string
192-
for _, orgID := range orgIDs {
193-
client = client.Clone().WithOrgID(orgID)
194-
resp, err := client.Datasources.GetDataSources()
195-
if err != nil {
196-
return nil, err
197-
}
198-
199-
for _, ds := range resp.Payload {
200-
if ds.ReadOnly {
201-
continue
202-
}
203-
ids = append(ids, MakeOrgResourceID(orgID, ds.UID))
192+
for _, ds := range resp.Payload {
193+
if ds.ReadOnly {
194+
continue
204195
}
196+
ids = append(ids, MakeOrgResourceID(orgID, ds.UID))
205197
}
206198

207199
return ids, nil

internal/resources/grafana/resource_folder.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ func resourceFolder() *common.Resource {
7878
"grafana_folder",
7979
orgResourceIDString("uid"),
8080
schema,
81-
).WithLister(listerFunction(listFolders))
81+
).WithLister(listerFunctionOrgResource(listFolders))
8282
}
8383

84-
func listFolders(ctx context.Context, client *goapi.GrafanaHTTPAPI, data *ListerData) ([]string, error) {
85-
return listDashboardOrFolder(client, data, "dash-folder")
84+
func listFolders(ctx context.Context, client *goapi.GrafanaHTTPAPI, orgID int64) ([]string, error) {
85+
return listDashboardOrFolder(client, orgID, "dash-folder")
8686
}
8787

8888
func CreateFolder(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {

0 commit comments

Comments
 (0)