Skip to content

Commit 80874e1

Browse files
Define org_id within the organization_preferences resource (#776)
* Define `org_id` within the `organization_preferences` resource Currently, the `org_id` is defined in the provider An OSS user who wants to manage orgs must first create orgs in one provider, then create a new provider to manage resources within it This PR is the start of work towards allowing #747 There are multiple benefits to setting the `org_id` in resources: 1. It removes the need to have a second provider instance when managing orgs, allowing for Terraform loops 2. It more clearly identifies which resources are org-specific. For example, a dashboard is org-scoped but a user is server-scoped * Remove unnecessary conversions * Update client * Remove "to be deprecated" notice
1 parent d4bf4f4 commit 80874e1

File tree

8 files changed

+55
-30
lines changed

8 files changed

+55
-30
lines changed

docs/data-sources/organization_preferences.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ data "grafana_organization_preferences" "test" {}
2525
- `home_dashboard_id` (Number) The Organization home dashboard ID.
2626
- `home_dashboard_uid` (String) The Organization home dashboard UID.
2727
- `id` (String) The ID of this resource.
28+
- `org_id` (Number) The Organization ID. If not set, the Org ID defined in the provider block will be used.
2829
- `theme` (String) The Organization theme. Available values are `light`, `dark`, or an empty string for the default.
2930
- `timezone` (String) The Organization timezone. Available values are `utc`, `browser`, or an empty string for the default.
3031
- `week_start` (String) The Organization week start.

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ resource "grafana_oncall_escalation" "example_notify_step" {
212212
- `insecure_skip_verify` (Boolean) Skip TLS certificate verification. May alternatively be set via the `GRAFANA_INSECURE_SKIP_VERIFY` environment variable.
213213
- `oncall_access_token` (String, Sensitive) A Grafana OnCall access token. May alternatively be set via the `GRAFANA_ONCALL_ACCESS_TOKEN` environment variable.
214214
- `oncall_url` (String) An Grafana OnCall backend address. May alternatively be set via the `GRAFANA_ONCALL_URL` environment variable.
215-
- `org_id` (Number) The organization id to operate on within grafana. May alternatively be set via the `GRAFANA_ORG_ID` environment variable.
215+
- `org_id` (Number) The default organization id to operate on within grafana. For resources that have an `org_id` attribute, the resource-level attribute has priority. May alternatively be set via the `GRAFANA_ORG_ID` environment variable.
216216
- `retries` (Number) The amount of retries to use for Grafana API calls. May alternatively be set via the `GRAFANA_RETRIES` environment variable.
217217
- `sm_access_token` (String, Sensitive) A Synthetic Monitoring access token. May alternatively be set via the `GRAFANA_SM_ACCESS_TOKEN` environment variable.
218218
- `sm_url` (String) Synthetic monitoring backend address. May alternatively be set via the `GRAFANA_SM_URL` environment variable. The correct value for each service region is cited in the [Synthetic Monitoring documentation](https://grafana.com/docs/grafana-cloud/synthetic-monitoring/private-probes/#probe-api-server-url). Note the `sm_url` value is optional, but it must correspond with the value specified as the `region_slug` in the `grafana_cloud_stack` resource. Also note that when a Terraform configuration contains multiple provider instances managing SM resources associated with the same Grafana stack, specifying an explicit `sm_url` set to the same value for each provider ensures all providers interact with the same SM API.

docs/resources/organization_preferences.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ resource "grafana_organization_preferences" "test" {
2828

2929
- `home_dashboard_id` (Number) The Organization home dashboard ID.
3030
- `home_dashboard_uid` (String) The Organization home dashboard UID.
31+
- `org_id` (Number) The Organization ID. If not set, the Org ID defined in the provider block will be used.
3132
- `theme` (String) The Organization theme. Available values are `light`, `dark`, or an empty string for the default.
3233
- `timezone` (String) The Organization timezone. Available values are `utc`, `browser`, or an empty string for the default.
3334
- `week_start` (String) The Organization week start.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.18
55
require (
66
github.com/Masterminds/semver/v3 v3.2.0
77
github.com/grafana/amixr-api-go-client v0.0.5
8-
github.com/grafana/grafana-api-golang-client v0.17.0
8+
github.com/grafana/grafana-api-golang-client v0.18.0
99
github.com/grafana/machine-learning-go-client v0.3.0
1010
github.com/grafana/synthetic-monitoring-agent v0.13.0
1111
github.com/grafana/synthetic-monitoring-api-go-client v0.6.5

go.sum

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
7777
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
7878
github.com/grafana/amixr-api-go-client v0.0.5 h1:jqmljnd5FozuOsCNuyhZVpooxmj0BW9MmeLA7PaLK6U=
7979
github.com/grafana/amixr-api-go-client v0.0.5/go.mod h1:N6x26XUrM5zGtK5zL5vNJnAn2JFMxLFPPLTw/6pDkFE=
80-
github.com/grafana/grafana-api-golang-client v0.17.0 h1:zNyiUJqtVvPTySS1GHp9vi83kiA5ocbI+tIbGCSh8bA=
81-
github.com/grafana/grafana-api-golang-client v0.17.0/go.mod h1:24W29gPe9yl0/3A9X624TPkAOR8DpHno490cPwnkv8E=
82-
github.com/grafana/machine-learning-go-client v0.2.1-0.20230104102917-b5fd232a6099 h1:YqRzJzgvjlpymwsj3ibMf4E2Drj99isJ4bXBDjVDOig=
83-
github.com/grafana/machine-learning-go-client v0.2.1-0.20230104102917-b5fd232a6099/go.mod h1:QFfZz8NkqVF8++skjkKQXJEZfpCYd8S0yTWJUpsLLTA=
84-
github.com/grafana/machine-learning-go-client v0.2.1-0.20230104114500-101b750dc038 h1:KdxXLroxzs71IVBXeJYZzzeRSZ7pOLmHHfrJnR7TSJA=
85-
github.com/grafana/machine-learning-go-client v0.2.1-0.20230104114500-101b750dc038/go.mod h1:QFfZz8NkqVF8++skjkKQXJEZfpCYd8S0yTWJUpsLLTA=
86-
github.com/grafana/machine-learning-go-client v0.2.1-0.20230105081721-98deec58b437 h1:FXRYFk+0CDFogvvwFynpIGa67d+i15h2YPnFigkv4S0=
87-
github.com/grafana/machine-learning-go-client v0.2.1-0.20230105081721-98deec58b437/go.mod h1:QFfZz8NkqVF8++skjkKQXJEZfpCYd8S0yTWJUpsLLTA=
80+
github.com/grafana/grafana-api-golang-client v0.18.0 h1:epv0GIyPka3R71hYNAfvzCpnbGmvbmwqho2sHMrSU6w=
81+
github.com/grafana/grafana-api-golang-client v0.18.0/go.mod h1:24W29gPe9yl0/3A9X624TPkAOR8DpHno490cPwnkv8E=
8882
github.com/grafana/machine-learning-go-client v0.3.0 h1:QmDPt9kFvw7RsVZE92V4tSbng2dHsOsVsHvNczLpNy8=
8983
github.com/grafana/machine-learning-go-client v0.3.0/go.mod h1:QFfZz8NkqVF8++skjkKQXJEZfpCYd8S0yTWJUpsLLTA=
9084
github.com/grafana/synthetic-monitoring-agent v0.13.0 h1:fUuWIYt2/4aYQ1QkAam5ATpecVrVU9a1/zIUv/6g7s4=

grafana/provider.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ func Provider(version string) func() *schema.Provider {
183183
},
184184
"org_id": {
185185
Type: schema.TypeInt,
186-
Required: true,
186+
Optional: true,
187187
DefaultFunc: schema.EnvDefaultFunc("GRAFANA_ORG_ID", 1),
188-
Description: "The organization id to operate on within grafana. May alternatively be set via the `GRAFANA_ORG_ID` environment variable.",
188+
Description: "The default organization id to operate on within grafana. For resources that have an `org_id` attribute, the resource-level attribute has priority. May alternatively be set via the `GRAFANA_ORG_ID` environment variable.",
189189
},
190190
"tls_key": {
191191
Type: schema.TypeString,
@@ -386,10 +386,10 @@ func createGrafanaClient(d *schema.ResourceData) (string, *gapi.Config, *gapi.Cl
386386
cfg := gapi.Config{
387387
Client: cli,
388388
NumRetries: d.Get("retries").(int),
389-
OrgID: int64(d.Get("org_id").(int)),
390389
}
391390
if len(auth) == 2 {
392391
cfg.BasicAuth = url.UserPassword(auth[0], auth[1])
392+
cfg.OrgID = int64(d.Get("org_id").(int))
393393
} else {
394394
cfg.APIKey = auth[0]
395395
}

grafana/resource_organization_preferences.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package grafana
22

33
import (
44
"context"
5+
"strconv"
56

67
gapi "github.com/grafana/grafana-api-golang-client"
78
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -26,6 +27,11 @@ func ResourceOrganizationPreferences() *schema.Resource {
2627
},
2728

2829
Schema: map[string]*schema.Schema{
30+
"org_id": {
31+
Type: schema.TypeInt,
32+
Optional: true,
33+
Description: "The Organization ID. If not set, the Org ID defined in the provider block will be used.",
34+
},
2935
"theme": {
3036
Type: schema.TypeString,
3137
Optional: true,
@@ -60,6 +66,11 @@ func ResourceOrganizationPreferences() *schema.Resource {
6066

6167
func CreateOrganizationPreferences(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
6268
client := meta.(*client).gapi
69+
id := d.Get("org_id").(int)
70+
if id > 0 {
71+
client = client.WithOrgID(int64(id))
72+
}
73+
6374
_, err := client.UpdateAllOrgPreferences(gapi.Preferences{
6475
Theme: d.Get("theme").(string),
6576
HomeDashboardID: int64(d.Get("home_dashboard_id").(int)),
@@ -71,13 +82,17 @@ func CreateOrganizationPreferences(ctx context.Context, d *schema.ResourceData,
7182
return diag.FromErr(err)
7283
}
7384

74-
d.SetId("organization_preferences")
85+
d.SetId(strconv.Itoa(id))
7586

7687
return ReadOrganizationPreferences(ctx, d, meta)
7788
}
7889

7990
func ReadOrganizationPreferences(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
8091
client := meta.(*client).gapi
92+
if id, _ := strconv.ParseInt(d.Id(), 10, 64); id > 0 {
93+
client = client.WithOrgID(id)
94+
}
95+
8196
prefs, err := client.OrgPreferences()
8297

8398
if err != nil {
@@ -90,8 +105,6 @@ func ReadOrganizationPreferences(ctx context.Context, d *schema.ResourceData, me
90105
d.Set("timezone", prefs.Timezone)
91106
d.Set("week_start", prefs.WeekStart)
92107

93-
d.SetId("organization_preferences")
94-
95108
return nil
96109
}
97110

@@ -101,6 +114,10 @@ func UpdateOrganizationPreferences(ctx context.Context, d *schema.ResourceData,
101114

102115
func DeleteOrganizationPreferences(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
103116
client := meta.(*client).gapi
117+
if id, _ := strconv.ParseInt(d.Id(), 10, 64); id > 0 {
118+
client = client.WithOrgID(id)
119+
}
120+
104121
if _, err := client.UpdateAllOrgPreferences(gapi.Preferences{}); err != nil {
105122
return diag.FromErr(err)
106123
}

grafana/resource_organization_preferences_test.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ package grafana
33
import (
44
"errors"
55
"fmt"
6+
"strconv"
67
"strings"
78
"testing"
89

910
gapi "github.com/grafana/grafana-api-golang-client"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
1012
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1113
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1214
)
@@ -31,16 +33,17 @@ func TestAccResourceOrganizationPreferences(t *testing.T) {
3133
WeekStart: "Monday",
3234
}
3335

34-
// TODO: Make parallizable
35-
resource.Test(t, resource.TestCase{
36+
testRandName := acctest.RandString(10)
37+
38+
resource.ParallelTest(t, resource.TestCase{
3639
ProviderFactories: testAccProviderFactories,
3740
CheckDestroy: testAccOrganizationPreferencesCheckDestroy(),
3841
Steps: []resource.TestStep{
3942
{
40-
Config: testOrganizationPreferencesConfig(prefs),
43+
Config: testOrganizationPreferencesConfig(testRandName, prefs),
4144
Check: resource.ComposeTestCheckFunc(
4245
testAccOrganizationPreferencesCheckExists("grafana_organization_preferences.test", prefs),
43-
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "id", "organization_preferences"),
46+
resource.TestMatchResourceAttr("grafana_organization_preferences.test", "id", idRegexp),
4447
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "theme", prefs.Theme),
4548
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "home_dashboard_id", "0"),
4649
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "home_dashboard_uid", ""),
@@ -49,10 +52,10 @@ func TestAccResourceOrganizationPreferences(t *testing.T) {
4952
),
5053
},
5154
{
52-
Config: testOrganizationPreferencesConfig(updatedPrefs),
55+
Config: testOrganizationPreferencesConfig(testRandName, updatedPrefs),
5356
Check: resource.ComposeTestCheckFunc(
5457
testAccOrganizationPreferencesCheckExists("grafana_organization_preferences.test", updatedPrefs),
55-
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "id", "organization_preferences"),
58+
resource.TestMatchResourceAttr("grafana_organization_preferences.test", "id", idRegexp),
5659
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "theme", updatedPrefs.Theme),
5760
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "home_dashboard_id", "0"),
5861
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "home_dashboard_uid", ""),
@@ -61,10 +64,10 @@ func TestAccResourceOrganizationPreferences(t *testing.T) {
6164
),
6265
},
6366
{
64-
Config: testOrganizationPreferencesConfig(finalPrefs),
67+
Config: testOrganizationPreferencesConfig(testRandName, finalPrefs),
6568
Check: resource.ComposeTestCheckFunc(
6669
testAccOrganizationPreferencesCheckExists("grafana_organization_preferences.test", finalPrefs),
67-
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "id", "organization_preferences"),
70+
resource.TestMatchResourceAttr("grafana_organization_preferences.test", "id", idRegexp),
6871
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "theme", finalPrefs.Theme),
6972
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "home_dashboard_id", "0"),
7073
resource.TestCheckResourceAttr("grafana_organization_preferences.test", "home_dashboard_uid", ""),
@@ -87,7 +90,11 @@ func testAccOrganizationPreferencesCheckExists(rn string, prefs gapi.Preferences
8790
return fmt.Errorf("resource id not set")
8891
}
8992

90-
client := testAccProvider.Meta().(*client).gapi
93+
id, err := strconv.ParseInt(rs.Primary.Attributes["org_id"], 10, 64)
94+
if err != nil {
95+
return fmt.Errorf("error parsing org_id: %s", err)
96+
}
97+
client := testAccProvider.Meta().(*client).gapi.WithOrgID(id)
9198
p, err := client.OrgPreferences()
9299
if err != nil {
93100
return fmt.Errorf("error getting organization preferences: %s", err)
@@ -127,12 +134,17 @@ func testAccOrganizationPreferencesCheckDestroy() resource.TestCheckFunc {
127134
}
128135
}
129136

130-
func testOrganizationPreferencesConfig(prefs gapi.Preferences) string {
137+
func testOrganizationPreferencesConfig(orgName string, prefs gapi.Preferences) string {
131138
return fmt.Sprintf(`
139+
resource "grafana_organization" "test" {
140+
name = "%[1]s"
141+
}
142+
132143
resource "grafana_organization_preferences" "test" {
133-
theme = "%s"
134-
timezone = "%s"
135-
week_start = "%s"
144+
org_id = grafana_organization.test.id
145+
theme = "%[2]s"
146+
timezone = "%[3]s"
147+
week_start = "%[4]s"
136148
}
137-
`, prefs.Theme, prefs.Timezone, prefs.WeekStart)
149+
`, orgName, prefs.Theme, prefs.Timezone, prefs.WeekStart)
138150
}

0 commit comments

Comments
 (0)