Skip to content

Commit 35008eb

Browse files
authored
Alerting: Fix grafana_contact_point ignores changes in secure fields (#880)
* Alerting: Fix grafana_contact_point ignores changes in secure fields Previously we suppressed the comparison of secure fields and stored "[REDACTED]" in state. This change will instead store the unredacted values in state on create/update and patch them during read. This way, Terraform can identify and update changed secure field values. * Fix issues caused by using gfState instead of tfState and not having uid during create * Fix linting
1 parent 9708599 commit 35008eb

File tree

3 files changed

+195
-142
lines changed

3 files changed

+195
-142
lines changed

internal/resources/grafana/resource_alerting_contact_point.go

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,16 @@ func createContactPoint(ctx context.Context, data *schema.ResourceData, meta int
136136
lock.Lock()
137137
defer lock.Unlock()
138138
for i := range ps {
139-
uid, err := client.NewContactPoint(&ps[i])
139+
p := ps[i]
140+
uid, err := client.NewContactPoint(&p.gfState)
140141
if err != nil {
141142
return diag.FromErr(err)
142143
}
143144
uids = append(uids, uid)
145+
146+
// Since this is a new resource, the proposed state won't have a UID.
147+
// We need the UID so that we can later associate it with the config returned in the api response.
148+
p.tfState["uid"] = uid
144149
}
145150

146151
data.SetId(packUIDs(uids))
@@ -159,11 +164,12 @@ func updateContactPoint(ctx context.Context, data *schema.ResourceData, meta int
159164
lock.Lock()
160165
defer lock.Unlock()
161166
for i := range ps {
162-
delete(unprocessedUIDs, ps[i].UID)
163-
err := client.UpdateContactPoint(&ps[i])
167+
p := ps[i].gfState
168+
delete(unprocessedUIDs, p.UID)
169+
err := client.UpdateContactPoint(&p)
164170
if err != nil {
165171
if strings.HasPrefix(err.Error(), "status: 404") {
166-
uid, err := client.NewContactPoint(&ps[i])
172+
uid, err := client.NewContactPoint(&p)
167173
newUIDs = append(newUIDs, uid)
168174
if err != nil {
169175
return diag.FromErr(err)
@@ -172,7 +178,7 @@ func updateContactPoint(ctx context.Context, data *schema.ResourceData, meta int
172178
}
173179
return diag.FromErr(err)
174180
}
175-
newUIDs = append(newUIDs, ps[i].UID)
181+
newUIDs = append(newUIDs, p.UID)
176182
}
177183

178184
// Any UIDs still left in the state that we haven't seen must map to deleted receivers.
@@ -205,13 +211,16 @@ func deleteContactPoint(ctx context.Context, data *schema.ResourceData, meta int
205211
return diag.Diagnostics{}
206212
}
207213

208-
func unpackContactPoints(data *schema.ResourceData) []gapi.ContactPoint {
209-
result := make([]gapi.ContactPoint, 0)
214+
func unpackContactPoints(data *schema.ResourceData) []statePair {
215+
result := make([]statePair, 0)
210216
name := data.Get("name").(string)
211217
for _, n := range notifiers {
212218
if points, ok := data.GetOk(n.meta().field); ok {
213219
for _, p := range points.([]interface{}) {
214-
result = append(result, unpackPointConfig(n, p, name))
220+
result = append(result, statePair{
221+
tfState: p.(map[string]interface{}),
222+
gfState: unpackPointConfig(n, p, name),
223+
})
215224
}
216225
}
217226
}
@@ -237,7 +246,7 @@ func packContactPoints(ps []gapi.ContactPoint, data *schema.ResourceData) error
237246

238247
for _, n := range notifiers {
239248
if p.Type == n.meta().typeStr {
240-
packed, err := n.pack(p)
249+
packed, err := n.pack(p, data)
241250
if err != nil {
242251
return err
243252
}
@@ -301,12 +310,6 @@ func commonNotifierResource() *schema.Resource {
301310
}
302311
}
303312

304-
const RedactedContactPointField = "[REDACTED]"
305-
306-
func redactedContactPointDiffSuppress(k, oldValue, newValue string, d *schema.ResourceData) bool {
307-
return oldValue == RedactedContactPointField
308-
}
309-
310313
const UIDSeparator = ";"
311314

312315
func packUIDs(uids []string) string {
@@ -328,14 +331,20 @@ func toUIDSet(uids []string) map[string]bool {
328331
type notifier interface {
329332
meta() notifierMeta
330333
schema() *schema.Resource
331-
pack(p gapi.ContactPoint) (interface{}, error)
334+
pack(p gapi.ContactPoint, data *schema.ResourceData) (interface{}, error)
332335
unpack(raw interface{}, name string) gapi.ContactPoint
333336
}
334337

335338
type notifierMeta struct {
336-
field string
337-
typeStr string
338-
desc string
339+
field string
340+
typeStr string
341+
desc string
342+
secureFields []string
343+
}
344+
345+
type statePair struct {
346+
tfState map[string]interface{}
347+
gfState gapi.ContactPoint
339348
}
340349

341350
func packNotifierStringField(gfSettings, tfSettings *map[string]interface{}, gfKey, tfKey string) {
@@ -345,8 +354,29 @@ func packNotifierStringField(gfSettings, tfSettings *map[string]interface{}, gfK
345354
}
346355
}
347356

357+
func packSecureFields(tfSettings, state map[string]interface{}, secureFields []string) {
358+
for _, tfKey := range secureFields {
359+
if v, ok := state[tfKey]; ok && v != nil {
360+
tfSettings[tfKey] = v.(string)
361+
}
362+
}
363+
}
364+
348365
func unpackNotifierStringField(tfSettings, gfSettings *map[string]interface{}, tfKey, gfKey string) {
349366
if v, ok := (*tfSettings)[tfKey]; ok && v != nil {
350367
(*gfSettings)[gfKey] = v.(string)
351368
}
352369
}
370+
371+
func getNotifierConfigFromStateWithUID(data *schema.ResourceData, n notifier, uid string) map[string]interface{} {
372+
if points, ok := data.GetOk(n.meta().field); ok {
373+
for _, pt := range points.([]interface{}) {
374+
config := pt.(map[string]interface{})
375+
if config["uid"] == uid {
376+
return config
377+
}
378+
}
379+
}
380+
381+
return nil
382+
}

0 commit comments

Comments
 (0)