Skip to content

Commit

Permalink
Self-contained cloud package
Browse files Browse the repository at this point in the history
Split from #1391
- Makes the resource functions private (exposed via a single map attribute) rather than each resource individually
- Puts the client validation in the cloud package
  • Loading branch information
julienduchesne committed Mar 2, 2024
1 parent 226d3f5 commit 9b26801
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 167 deletions.
24 changes: 2 additions & 22 deletions internal/provider/legacy_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,6 @@ func Provider(version string) *schema.Provider {
"grafana_synthetic_monitoring_probe": syntheticmonitoring.ResourceProbe(),
})

// Resources that require the Cloud client to exist.
cloudClientResources = addResourcesMetadataValidation(cloudClientPresent, map[string]*schema.Resource{
"grafana_cloud_access_policy": cloud.ResourceAccessPolicy(),
"grafana_cloud_access_policy_token": cloud.ResourceAccessPolicyToken(),
"grafana_cloud_api_key": cloud.ResourceAPIKey(),
"grafana_cloud_plugin_installation": cloud.ResourcePluginInstallation(),
"grafana_cloud_stack": cloud.ResourceStack(),
"grafana_cloud_stack_api_key": cloud.ResourceStackAPIKey(),
"grafana_cloud_stack_service_account": cloud.ResourceStackServiceAccount(),
"grafana_cloud_stack_service_account_token": cloud.ResourceStackServiceAccountToken(),
"grafana_synthetic_monitoring_installation": cloud.ResourceInstallation(),
})

// Resources that require the OnCall client to exist.
onCallClientResources = addResourcesMetadataValidation(onCallClientPresent, map[string]*schema.Resource{
"grafana_oncall_integration": oncall.ResourceIntegration(),
Expand Down Expand Up @@ -138,13 +125,6 @@ func Provider(version string) *schema.Provider {
"grafana_synthetic_monitoring_probes": syntheticmonitoring.DataSourceProbes(),
})

// Datasources that require the Cloud client to exist.
cloudClientDatasources = addResourcesMetadataValidation(cloudClientPresent, map[string]*schema.Resource{
"grafana_cloud_ips": cloud.DataSourceIPs(),
"grafana_cloud_organization": cloud.DataSourceOrganization(),
"grafana_cloud_stack": cloud.DataSourceStack(),
})

// Datasources that require the OnCall client to exist.
onCallClientDatasources = addResourcesMetadataValidation(onCallClientPresent, map[string]*schema.Resource{
"grafana_oncall_user": oncall.DataSourceUser(),
Expand Down Expand Up @@ -279,14 +259,14 @@ func Provider(version string) *schema.Provider {
grafanaClientResources,
smClientResources,
onCallClientResources,
cloudClientResources,
cloud.ResourcesMap,
),

DataSourcesMap: mergeResourceMaps(
grafanaClientDatasources,
smClientDatasources,
onCallClientDatasources,
cloudClientDatasources,
cloud.DatasourcesMap,
),
}

Expand Down
7 changes: 0 additions & 7 deletions internal/provider/legacy_provider_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ func smClientPresent(resourceName string, d *schema.ResourceData, m interface{})
return nil
}

func cloudClientPresent(resourceName string, d *schema.ResourceData, m interface{}) error {
if m.(*common.Client).GrafanaCloudAPI == nil {
return fmt.Errorf("the Cloud API client is required for `%s`. Set the cloud_api_key provider attribute", resourceName)
}
return nil
}

func onCallClientPresent(resourceName string, d *schema.ResourceData, m interface{}) error {
if m.(*common.Client).OnCallClient == nil {
return fmt.Errorf("the Oncall client is required for `%s`. Set the oncall_access_token provider attribute", resourceName)
Expand Down
16 changes: 16 additions & 0 deletions internal/resources/cloud/common.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package cloud

import (
"context"

"github.com/grafana/grafana-com-public-clients/go/gcom"
"github.com/grafana/terraform-provider-grafana/internal/common"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func ClientRequestID() string {
Expand All @@ -14,6 +18,18 @@ func ClientRequestID() string {
return "tf-" + uuid
}

type crudWithClientFunc func(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics

func withClient[T schema.CreateContextFunc | schema.UpdateContextFunc | schema.ReadContextFunc | schema.DeleteContextFunc](f crudWithClientFunc) T {
return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI
if client == nil {
return diag.Errorf("the Cloud API client is required for this resource. Set the cloud_access_policy_token provider attribute")
}
return f(ctx, d, client)
}
}

func apiError(err error) diag.Diagnostics {
if err == nil {
return nil
Expand Down
6 changes: 3 additions & 3 deletions internal/resources/cloud/data_source_cloud_ips.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func DataSourceIPs() *schema.Resource {
func datasourceIPs() *schema.Resource {
return &schema.Resource{
Description: "Data source for retrieving sets of cloud IPs. See https://grafana.com/docs/grafana-cloud/reference/allow-list/ for more info",
ReadContext: DataSourceIPsRead,
ReadContext: datasourceIPsRead,
Schema: map[string]*schema.Schema{
"hosted_alerts": {
Description: "Set of IP addresses that are used for hosted alerts.",
Expand Down Expand Up @@ -59,7 +59,7 @@ func DataSourceIPs() *schema.Resource {
}
}

func DataSourceIPsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
func datasourceIPsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
d.SetId("cloud_ips")
for attr, dataURL := range map[string]string{
"hosted_alerts": "https://grafana.com/api/hosted-alerts/source-ips.txt",
Expand Down
10 changes: 4 additions & 6 deletions internal/resources/cloud/data_source_cloud_organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import (
"context"
"strconv"

"github.com/grafana/terraform-provider-grafana/internal/common"
"github.com/grafana/grafana-com-public-clients/go/gcom"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func DataSourceOrganization() *schema.Resource {
func datasourceOrganization() *schema.Resource {
return &schema.Resource{
ReadContext: DataSourceOrganizationRead,
ReadContext: withClient[schema.ReadContextFunc](datasourceOrganizationRead),
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Expand Down Expand Up @@ -43,9 +43,7 @@ func DataSourceOrganization() *schema.Resource {
}
}

func DataSourceOrganizationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI

func datasourceOrganizationRead(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
id := d.Get("id").(string)
if id == "" {
id = d.Get("slug").(string)
Expand Down
11 changes: 6 additions & 5 deletions internal/resources/cloud/data_source_cloud_stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ package cloud
import (
"context"

"github.com/grafana/grafana-com-public-clients/go/gcom"
"github.com/grafana/terraform-provider-grafana/internal/common"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func DataSourceStack() *schema.Resource {
func datasourceStack() *schema.Resource {
return &schema.Resource{
Description: "Data source for Grafana Stack",
ReadContext: DataSourceStackRead,
Schema: common.CloneResourceSchemaForDatasource(ResourceStack(), map[string]*schema.Schema{
ReadContext: withClient[schema.ReadContextFunc](datasourceStackRead),
Schema: common.CloneResourceSchemaForDatasource(resourceStack(), map[string]*schema.Schema{
"slug": {
Type: schema.TypeString,
Required: true,
Expand All @@ -31,7 +32,7 @@ available at “https://<stack_slug>.grafana.net".`,
}
}

func DataSourceStackRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
func datasourceStackRead(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
d.SetId(d.Get("slug").(string))
return ReadStack(ctx, d, meta)
return readStack(ctx, d, client)
}
29 changes: 11 additions & 18 deletions internal/resources/cloud/resource_cloud_access_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

var ResourceAccessPolicyID = common.NewResourceIDWithLegacySeparator("grafana_cloud_access_policy", "/", "region", "policyId") //nolint:staticcheck

func ResourceAccessPolicy() *schema.Resource {
func resourceAccessPolicy() *schema.Resource {
return &schema.Resource{

Description: `
Expand All @@ -29,10 +29,10 @@ Required access policy scopes:
* accesspolicies:delete
`,

CreateContext: CreateCloudAccessPolicy,
UpdateContext: UpdateCloudAccessPolicy,
DeleteContext: DeleteCloudAccessPolicy,
ReadContext: ReadCloudAccessPolicy,
CreateContext: withClient[schema.CreateContextFunc](createCloudAccessPolicy),
UpdateContext: withClient[schema.UpdateContextFunc](updateCloudAccessPolicy),
DeleteContext: withClient[schema.DeleteContextFunc](deleteCloudAccessPolicy),
ReadContext: withClient[schema.ReadContextFunc](readCloudAccessPolicy),

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
Expand Down Expand Up @@ -126,8 +126,7 @@ var cloudAccessPolicyRealmSchema = &schema.Resource{
},
}

func CreateCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI
func createCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
region := d.Get("region").(string)

displayName := d.Get("display_name").(string)
Expand All @@ -149,12 +148,10 @@ func CreateCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, meta i

d.SetId(ResourceAccessPolicyID.Make(region, result.Id))

return ReadCloudAccessPolicy(ctx, d, meta)
return readCloudAccessPolicy(ctx, d, client)
}

func UpdateCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI

func updateCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
split, err := ResourceAccessPolicyID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
Expand All @@ -176,12 +173,10 @@ func UpdateCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, meta i
return apiError(err)
}

return ReadCloudAccessPolicy(ctx, d, meta)
return readCloudAccessPolicy(ctx, d, client)
}

func ReadCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI

func readCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
split, err := ResourceAccessPolicyID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
Expand All @@ -208,9 +203,7 @@ func ReadCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, meta int
return nil
}

func DeleteCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI

func deleteCloudAccessPolicy(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
split, err := ResourceAccessPolicyID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
Expand Down
29 changes: 11 additions & 18 deletions internal/resources/cloud/resource_cloud_access_policy_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

var ResourceAccessPolicyTokenID = common.NewResourceIDWithLegacySeparator("grafana_cloud_access_policy_token", "/", "region", "tokenId") //nolint:staticcheck

func ResourceAccessPolicyToken() *schema.Resource {
func resourceAccessPolicyToken() *schema.Resource {
return &schema.Resource{

Description: `
Expand All @@ -27,10 +27,10 @@ Required access policy scopes:
* accesspolicies:delete
`,

CreateContext: CreateCloudAccessPolicyToken,
UpdateContext: UpdateCloudAccessPolicyToken,
DeleteContext: DeleteCloudAccessPolicyToken,
ReadContext: ReadCloudAccessPolicyToken,
CreateContext: withClient[schema.CreateContextFunc](createCloudAccessPolicyToken),
UpdateContext: withClient[schema.UpdateContextFunc](updateCloudAccessPolicyToken),
DeleteContext: withClient[schema.DeleteContextFunc](deleteCloudAccessPolicyToken),
ReadContext: withClient[schema.ReadContextFunc](readCloudAccessPolicyToken),

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
Expand Down Expand Up @@ -94,8 +94,7 @@ Required access policy scopes:
}
}

func CreateCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI
func createCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
region := d.Get("region").(string)

tokenInput := gcom.PostTokensRequest{
Expand All @@ -121,12 +120,10 @@ func CreateCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, m
d.SetId(ResourceAccessPolicyTokenID.Make(region, result.Id))
d.Set("token", result.Token)

return ReadCloudAccessPolicyToken(ctx, d, meta)
return readCloudAccessPolicyToken(ctx, d, client)
}

func UpdateCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI

func updateCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
split, err := ResourceAccessPolicyTokenID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
Expand All @@ -145,12 +142,10 @@ func UpdateCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, m
return apiError(err)
}

return ReadCloudAccessPolicyToken(ctx, d, meta)
return readCloudAccessPolicyToken(ctx, d, client)
}

func ReadCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI

func readCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
split, err := ResourceAccessPolicyTokenID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
Expand Down Expand Up @@ -178,9 +173,7 @@ func ReadCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, met
return nil
}

func DeleteCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI

func deleteCloudAccessPolicyToken(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
split, err := ResourceAccessPolicyTokenID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
Expand Down
22 changes: 8 additions & 14 deletions internal/resources/cloud/resource_cloud_api_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
var ResourceAPIKeyID = common.NewResourceIDWithLegacySeparator("grafana_cloud_api_key", "-", "orgSlug", "apiKeyName") //nolint:staticcheck
var cloudAPIKeyRoles = []string{"Viewer", "Editor", "Admin", "MetricsPublisher", "PluginPublisher"}

func ResourceAPIKey() *schema.Resource {
func resourceAPIKey() *schema.Resource {
return &schema.Resource{
Description: `This resource is deprecated and will be removed in a future release. Please use grafana_cloud_access_policy instead.
Expand All @@ -27,9 +27,9 @@ Required access policy scopes:
* api-keys:write
* api-keys:delete
`,
CreateContext: ResourceAPIKeyCreate,
ReadContext: ResourceAPIKeyRead,
DeleteContext: ResourceAPIKeyDelete,
CreateContext: withClient[schema.CreateContextFunc](resourceAPIKeyCreate),
ReadContext: withClient[schema.ReadContextFunc](resourceAPIKeyRead),
DeleteContext: withClient[schema.DeleteContextFunc](resourceAPIKeyDelete),
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Expand Down Expand Up @@ -65,9 +65,7 @@ Required access policy scopes:
}
}

func ResourceAPIKeyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c := meta.(*common.Client).GrafanaCloudAPI

func resourceAPIKeyCreate(ctx context.Context, d *schema.ResourceData, c *gcom.APIClient) diag.Diagnostics {
req := gcom.PostApiKeysRequest{
Name: d.Get("name").(string),
Role: d.Get("role").(string),
Expand All @@ -85,12 +83,10 @@ func ResourceAPIKeyCreate(ctx context.Context, d *schema.ResourceData, meta inte
d.Set("key", *resp.Token)
d.SetId(ResourceAPIKeyID.Make(org, resp.Name))

return ResourceAPIKeyRead(ctx, d, meta)
return resourceAPIKeyRead(ctx, d, c)
}

func ResourceAPIKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c := meta.(*common.Client).GrafanaCloudAPI

func resourceAPIKeyRead(ctx context.Context, d *schema.ResourceData, c *gcom.APIClient) diag.Diagnostics {
split, err := ResourceAPIKeyID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
Expand All @@ -110,9 +106,7 @@ func ResourceAPIKeyRead(ctx context.Context, d *schema.ResourceData, meta interf
return nil
}

func ResourceAPIKeyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c := meta.(*common.Client).GrafanaCloudAPI

func resourceAPIKeyDelete(ctx context.Context, d *schema.ResourceData, c *gcom.APIClient) diag.Diagnostics {
split, err := ResourceAPIKeyID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
Expand Down
Loading

0 comments on commit 9b26801

Please sign in to comment.