Skip to content

Commit 9ded25e

Browse files
anGie44matthiasngjulienduchesne
authored
feat: new resource grafana_playlist (#264)
* add playlist resource * update logging * update example format * remove duplicate attribute check Co-authored-by: matthiasng <[email protected]> * update client usage * Make linter pass * Add doc for playlist Co-authored-by: matthiasng <[email protected]> Co-authored-by: Julien Duchesne <[email protected]>
1 parent 351fdb6 commit 9ded25e

File tree

5 files changed

+474
-0
lines changed

5 files changed

+474
-0
lines changed

docs/resources/playlist.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "grafana_playlist Resource - terraform-provider-grafana"
4+
subcategory: ""
5+
description: |-
6+
* [Official documentation](https://grafana.com/docs/grafana/latest/dashboards/playlist/)
7+
* [HTTP API](https://grafana.com/docs/grafana/latest/http_api/playlist/)
8+
---
9+
10+
# grafana_playlist (Resource)
11+
12+
* [Official documentation](https://grafana.com/docs/grafana/latest/dashboards/playlist/)
13+
* [HTTP API](https://grafana.com/docs/grafana/latest/http_api/playlist/)
14+
15+
16+
17+
<!-- schema generated by tfplugindocs -->
18+
## Schema
19+
20+
### Required
21+
22+
- **interval** (String)
23+
- **item** (Block Set, Min: 1) (see [below for nested schema](#nestedblock--item))
24+
- **name** (String) The name of the playlist.
25+
26+
### Optional
27+
28+
- **id** (String) The ID of this resource.
29+
30+
### Read-Only
31+
32+
- **org_id** (String)
33+
34+
<a id="nestedblock--item"></a>
35+
### Nested Schema for `item`
36+
37+
Required:
38+
39+
- **order** (Number)
40+
- **title** (String)
41+
42+
Optional:
43+
44+
- **type** (String)
45+
- **value** (String)
46+
47+
Read-Only:
48+
49+
- **id** (String) The ID of this resource.
50+
51+

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd
106106
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
107107
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
108108
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
109+
github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U=
109110
github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
110111
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
111112
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I=
@@ -1207,6 +1208,7 @@ golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBc
12071208
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
12081209
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
12091210
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
1211+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
12101212
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
12111213
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
12121214
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

grafana/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ func Provider(version string) func() *schema.Provider {
109109
"grafana_folder": ResourceFolder(),
110110
"grafana_folder_permission": ResourceFolderPermission(),
111111
"grafana_organization": ResourceOrganization(),
112+
"grafana_playlist": ResourcePlaylist(),
112113
"grafana_role": ResourceRole(),
113114
"grafana_team": ResourceTeam(),
114115
"grafana_team_preferences": ResourceTeamPreferences(),

grafana/resource_playlist.go

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package grafana
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"strconv"
8+
"strings"
9+
10+
gapi "github.com/grafana/grafana-api-golang-client"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
13+
)
14+
15+
func ResourcePlaylist() *schema.Resource {
16+
return &schema.Resource{
17+
CreateContext: CreatePlaylist,
18+
ReadContext: ReadPlaylist,
19+
UpdateContext: UpdatePlaylist,
20+
DeleteContext: DeletePlaylist,
21+
Importer: &schema.ResourceImporter{
22+
StateContext: schema.ImportStatePassthroughContext,
23+
},
24+
25+
Description: `
26+
* [Official documentation](https://grafana.com/docs/grafana/latest/dashboards/playlist/)
27+
* [HTTP API](https://grafana.com/docs/grafana/latest/http_api/playlist/)
28+
`,
29+
30+
Schema: map[string]*schema.Schema{
31+
"name": {
32+
Type: schema.TypeString,
33+
Required: true,
34+
ForceNew: true,
35+
Description: "The name of the playlist.",
36+
},
37+
"interval": {
38+
Type: schema.TypeString,
39+
Required: true,
40+
},
41+
"item": {
42+
Type: schema.TypeSet,
43+
Required: true,
44+
Elem: &schema.Resource{
45+
Schema: map[string]*schema.Schema{
46+
"id": {
47+
Type: schema.TypeString,
48+
Computed: true,
49+
},
50+
"order": {
51+
Type: schema.TypeInt,
52+
Required: true,
53+
},
54+
"title": {
55+
Type: schema.TypeString,
56+
Required: true,
57+
},
58+
"type": {
59+
Type: schema.TypeString,
60+
Optional: true,
61+
},
62+
"value": {
63+
Type: schema.TypeString,
64+
Optional: true,
65+
},
66+
},
67+
},
68+
},
69+
"org_id": {
70+
Type: schema.TypeString,
71+
Computed: true,
72+
},
73+
},
74+
}
75+
}
76+
77+
func CreatePlaylist(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
78+
client := meta.(*client).gapi
79+
80+
playlist := gapi.Playlist{
81+
Name: d.Get("name").(string),
82+
Interval: d.Get("interval").(string),
83+
Items: expandPlaylistItems(d.Get("item").(*schema.Set).List()),
84+
}
85+
86+
id, err := client.NewPlaylist(playlist)
87+
88+
if err != nil {
89+
return diag.FromErr(fmt.Errorf("error creating Playlist: %w", err))
90+
}
91+
92+
d.SetId(strconv.Itoa(id))
93+
94+
return ReadPlaylist(ctx, d, meta)
95+
}
96+
97+
func ReadPlaylist(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
98+
client := meta.(*client).gapi
99+
100+
id, err := strconv.Atoi(d.Id())
101+
if err != nil {
102+
return diag.FromErr(fmt.Errorf("error reading Playlist (%s): %w", d.Id(), err))
103+
}
104+
105+
resp, err := client.Playlist(id)
106+
107+
if err != nil {
108+
if strings.HasPrefix(err.Error(), "status: 404") {
109+
log.Printf("[WARN] removing playlist %d from state because it no longer exists in grafana", id)
110+
d.SetId("")
111+
return nil
112+
}
113+
return diag.FromErr(fmt.Errorf("error reading Playlist (%s): %w", d.Id(), err))
114+
}
115+
116+
d.Set("name", resp.Name)
117+
d.Set("interval", resp.Interval)
118+
if err := d.Set("item", flattenPlaylistItems(resp.Items)); err != nil {
119+
return diag.FromErr(fmt.Errorf("error setting item: %v", err))
120+
}
121+
122+
return nil
123+
}
124+
125+
func UpdatePlaylist(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
126+
client := meta.(*client).gapi
127+
128+
playlist := gapi.Playlist{
129+
Name: d.Get("name").(string),
130+
Interval: d.Get("interval").(string),
131+
Items: expandPlaylistItems(d.Get("item").(*schema.Set).List()),
132+
}
133+
134+
err := client.UpdatePlaylist(playlist)
135+
if err != nil {
136+
return diag.FromErr(fmt.Errorf("error updating Playlist (%s): %w", d.Id(), err))
137+
}
138+
139+
return ReadPlaylist(ctx, d, meta)
140+
}
141+
142+
func DeletePlaylist(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
143+
client := meta.(*client).gapi
144+
145+
id, err := strconv.Atoi(d.Id())
146+
147+
if err != nil {
148+
return diag.FromErr(fmt.Errorf("error deleting Playlist (%s): %w", d.Id(), err))
149+
}
150+
151+
if err := client.DeletePlaylist(id); err != nil {
152+
if strings.HasPrefix(err.Error(), "status: 404") {
153+
return nil
154+
}
155+
return diag.FromErr(fmt.Errorf("error deleting Playlist (%s): %w", d.Id(), err))
156+
}
157+
158+
return nil
159+
}
160+
161+
func expandPlaylistItems(items []interface{}) []gapi.PlaylistItem {
162+
playlistItems := make([]gapi.PlaylistItem, 0)
163+
for _, item := range items {
164+
itemMap := item.(map[string]interface{})
165+
p := gapi.PlaylistItem{
166+
Order: itemMap["order"].(int),
167+
Title: itemMap["title"].(string),
168+
}
169+
if v, ok := itemMap["type"].(string); ok {
170+
p.Type = v
171+
}
172+
if v, ok := itemMap["value"].(string); ok {
173+
p.Value = v
174+
}
175+
playlistItems = append(playlistItems, p)
176+
}
177+
return playlistItems
178+
}
179+
180+
func flattenPlaylistItems(items []gapi.PlaylistItem) []interface{} {
181+
playlistItems := make([]interface{}, 0)
182+
for _, item := range items {
183+
p := map[string]interface{}{
184+
"type": item.Type,
185+
"value": item.Value,
186+
"order": item.Order,
187+
"title": item.Title,
188+
}
189+
playlistItems = append(playlistItems, p)
190+
}
191+
return playlistItems
192+
}

0 commit comments

Comments
 (0)