Skip to content

Commit 4a60e18

Browse files
stackdriver dashboards resource (#3490) (#2088)
Signed-off-by: Modular Magician <[email protected]>
1 parent 227071f commit 4a60e18

19 files changed

+662
-31
lines changed

.changelog/3490.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:new-resource
2+
`google_monitoring_dashboard`
3+
```
4+
```release-note:breaking-change
5+
The base url for the `monitoring` endpoint no longer includes the API version (previously "v3/"). If you use a `monitoring_custom_endpoint`, remove the trailing "v3/".
6+
```

google-beta/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ var IdentityPlatformDefaultBasePath = "https://identitytoolkit.googleapis.com/v2
260260
var KMSDefaultBasePath = "https://cloudkms.googleapis.com/v1/"
261261
var LoggingDefaultBasePath = "https://logging.googleapis.com/v2/"
262262
var MLEngineDefaultBasePath = "https://ml.googleapis.com/v1/"
263-
var MonitoringDefaultBasePath = "https://monitoring.googleapis.com/v3/"
263+
var MonitoringDefaultBasePath = "https://monitoring.googleapis.com/"
264264
var OSLoginDefaultBasePath = "https://oslogin.googleapis.com/v1/"
265265
var PubsubDefaultBasePath = "https://pubsub.googleapis.com/v1/"
266266
var RedisDefaultBasePath = "https://redis.googleapis.com/v1beta1/"

google-beta/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
931931
"google_kms_crypto_key_iam_binding": ResourceIamBinding(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
932932
"google_kms_crypto_key_iam_member": ResourceIamMember(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
933933
"google_kms_crypto_key_iam_policy": ResourceIamPolicy(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
934+
"google_monitoring_dashboard": resourceMonitoringDashboard(),
934935
"google_service_networking_connection": resourceServiceNetworkingConnection(),
935936
"google_spanner_instance_iam_binding": ResourceIamBinding(IamSpannerInstanceSchema, NewSpannerInstanceIamUpdater, SpannerInstanceIdParseFunc),
936937
"google_spanner_instance_iam_member": ResourceIamMember(IamSpannerInstanceSchema, NewSpannerInstanceIamUpdater, SpannerInstanceIdParseFunc),

google-beta/resource_monitoring_alert_policy.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ func resourceMonitoringAlertPolicyCreate(d *schema.ResourceData, meta interface{
775775
mutexKV.Lock(lockName)
776776
defer mutexKV.Unlock(lockName)
777777

778-
url, err := replaceVars(d, config, "{{MonitoringBasePath}}projects/{{project}}/alertPolicies")
778+
url, err := replaceVars(d, config, "{{MonitoringBasePath}}v3/projects/{{project}}/alertPolicies")
779779
if err != nil {
780780
return err
781781
}
@@ -816,7 +816,7 @@ func resourceMonitoringAlertPolicyCreate(d *schema.ResourceData, meta interface{
816816
func resourceMonitoringAlertPolicyRead(d *schema.ResourceData, meta interface{}) error {
817817
config := meta.(*Config)
818818

819-
url, err := replaceVars(d, config, "{{MonitoringBasePath}}{{name}}")
819+
url, err := replaceVars(d, config, "{{MonitoringBasePath}}v3/{{name}}")
820820
if err != nil {
821821
return err
822822
}
@@ -936,7 +936,7 @@ func resourceMonitoringAlertPolicyUpdate(d *schema.ResourceData, meta interface{
936936
mutexKV.Lock(lockName)
937937
defer mutexKV.Unlock(lockName)
938938

939-
url, err := replaceVars(d, config, "{{MonitoringBasePath}}{{name}}")
939+
url, err := replaceVars(d, config, "{{MonitoringBasePath}}v3/{{name}}")
940940
if err != nil {
941941
return err
942942
}
@@ -1001,7 +1001,7 @@ func resourceMonitoringAlertPolicyDelete(d *schema.ResourceData, meta interface{
10011001
mutexKV.Lock(lockName)
10021002
defer mutexKV.Unlock(lockName)
10031003

1004-
url, err := replaceVars(d, config, "{{MonitoringBasePath}}{{name}}")
1004+
url, err := replaceVars(d, config, "{{MonitoringBasePath}}v3/{{name}}")
10051005
if err != nil {
10061006
return err
10071007
}
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package google
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"time"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
9+
"github.com/hashicorp/terraform-plugin-sdk/helper/structure"
10+
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
11+
)
12+
13+
func monitoringDashboardDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
14+
computedFields := []string{"etag", "name"}
15+
16+
oldMap, err := structure.ExpandJsonFromString(old)
17+
if err != nil {
18+
return false
19+
}
20+
21+
newMap, err := structure.ExpandJsonFromString(new)
22+
if err != nil {
23+
return false
24+
}
25+
26+
for _, f := range computedFields {
27+
delete(oldMap, f)
28+
delete(newMap, f)
29+
}
30+
31+
return reflect.DeepEqual(oldMap, newMap)
32+
}
33+
34+
func resourceMonitoringDashboard() *schema.Resource {
35+
return &schema.Resource{
36+
Create: resourceMonitoringDashboardCreate,
37+
Read: resourceMonitoringDashboardRead,
38+
Update: resourceMonitoringDashboardUpdate,
39+
Delete: resourceMonitoringDashboardDelete,
40+
41+
Importer: &schema.ResourceImporter{
42+
State: resourceMonitoringDashboardImport,
43+
},
44+
45+
Timeouts: &schema.ResourceTimeout{
46+
Create: schema.DefaultTimeout(4 * time.Minute),
47+
Update: schema.DefaultTimeout(4 * time.Minute),
48+
Delete: schema.DefaultTimeout(4 * time.Minute),
49+
},
50+
51+
Schema: map[string]*schema.Schema{
52+
"dashboard_json": {
53+
Type: schema.TypeString,
54+
Required: true,
55+
ValidateFunc: validation.ValidateJsonString,
56+
DiffSuppressFunc: monitoringDashboardDiffSuppress,
57+
StateFunc: func(v interface{}) string {
58+
json, _ := structure.NormalizeJsonString(v)
59+
return json
60+
},
61+
},
62+
"project": {
63+
Type: schema.TypeString,
64+
Optional: true,
65+
Computed: true,
66+
ForceNew: true,
67+
},
68+
},
69+
}
70+
}
71+
72+
func resourceMonitoringDashboardCreate(d *schema.ResourceData, meta interface{}) error {
73+
config := meta.(*Config)
74+
75+
obj, err := structure.ExpandJsonFromString(d.Get("dashboard_json").(string))
76+
if err != nil {
77+
return err
78+
}
79+
80+
project, err := getProject(d, config)
81+
if err != nil {
82+
return err
83+
}
84+
85+
url, err := replaceVars(d, config, "{{MonitoringBasePath}}v1/projects/{{project}}/dashboards")
86+
if err != nil {
87+
return err
88+
}
89+
res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutCreate), isMonitoringRetryableError)
90+
if err != nil {
91+
return fmt.Errorf("Error creating Dashboard: %s", err)
92+
}
93+
94+
name, ok := res["name"]
95+
if !ok {
96+
return fmt.Errorf("Create response didn't contain critical fields. Create may not have succeeded.")
97+
}
98+
d.SetId(name.(string))
99+
100+
return resourceMonitoringDashboardRead(d, config)
101+
}
102+
103+
func resourceMonitoringDashboardRead(d *schema.ResourceData, meta interface{}) error {
104+
config := meta.(*Config)
105+
106+
url := config.MonitoringBasePath + "v1/" + d.Id()
107+
108+
project, err := getProject(d, config)
109+
if err != nil {
110+
return err
111+
}
112+
113+
res, err := sendRequest(config, "GET", project, url, nil, isMonitoringRetryableError)
114+
if err != nil {
115+
return handleNotFoundError(err, d, fmt.Sprintf("MonitoringDashboard %q", d.Id()))
116+
}
117+
118+
if err := d.Set("project", project); err != nil {
119+
return fmt.Errorf("Error reading Dashboard: %s", err)
120+
}
121+
122+
str, err := structure.FlattenJsonToString(res)
123+
if err != nil {
124+
return fmt.Errorf("Error reading Dashboard: %s", err)
125+
}
126+
if err = d.Set("dashboard_json", str); err != nil {
127+
return fmt.Errorf("Error reading Dashboard: %s", err)
128+
}
129+
130+
return nil
131+
}
132+
133+
func resourceMonitoringDashboardUpdate(d *schema.ResourceData, meta interface{}) error {
134+
config := meta.(*Config)
135+
136+
o, n := d.GetChange("dashboard_json")
137+
oObj, err := structure.ExpandJsonFromString(o.(string))
138+
if err != nil {
139+
return err
140+
}
141+
nObj, err := structure.ExpandJsonFromString(n.(string))
142+
if err != nil {
143+
return err
144+
}
145+
146+
nObj["etag"] = oObj["etag"]
147+
148+
project, err := getProject(d, config)
149+
if err != nil {
150+
return err
151+
}
152+
153+
url := config.MonitoringBasePath + "v1/" + d.Id()
154+
_, err = sendRequestWithTimeout(config, "PATCH", project, url, nObj, d.Timeout(schema.TimeoutUpdate), isMonitoringRetryableError)
155+
if err != nil {
156+
return fmt.Errorf("Error updating Dashboard %q: %s", d.Id(), err)
157+
}
158+
159+
return resourceMonitoringDashboardRead(d, config)
160+
}
161+
162+
func resourceMonitoringDashboardDelete(d *schema.ResourceData, meta interface{}) error {
163+
config := meta.(*Config)
164+
165+
url := config.MonitoringBasePath + "v1/" + d.Id()
166+
167+
project, err := getProject(d, config)
168+
if err != nil {
169+
return err
170+
}
171+
172+
_, err = sendRequestWithTimeout(config, "DELETE", project, url, nil, d.Timeout(schema.TimeoutDelete), isMonitoringRetryableError)
173+
if err != nil {
174+
return handleNotFoundError(err, d, fmt.Sprintf("MonitoringDashboard %q", d.Id()))
175+
}
176+
177+
return nil
178+
}
179+
180+
func resourceMonitoringDashboardImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
181+
config := meta.(*Config)
182+
183+
// current import_formats can't import fields with forward slashes in their value
184+
parts, err := getImportIdQualifiers([]string{"projects/(?P<project>[^/]+)/dashboards/(?P<id>[^/]+)", "(?P<id>[^/]+)"}, d, config, d.Id())
185+
if err != nil {
186+
return nil, err
187+
}
188+
189+
d.Set("project", parts["project"])
190+
d.SetId(fmt.Sprintf("projects/%s/dashboards/%s", parts["project"], parts["id"]))
191+
192+
return []*schema.ResourceData{d}, nil
193+
}

0 commit comments

Comments
 (0)