Skip to content

Commit

Permalink
Cloud: Make full use of ID + import generation framework (#1412)
Browse files Browse the repository at this point in the history
Split from #1391
Convert the `stack` and `stack_service_account` resources to the new ID system that validates the ID format
  • Loading branch information
julienduchesne authored Mar 11, 2024
1 parent 6f8876c commit c8ac63a
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 36 deletions.
3 changes: 1 addition & 2 deletions docs/resources/cloud_stack.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,5 @@ resource "grafana_cloud_stack" "test" {
Import is supported using the following syntax:

```shell
terraform import grafana_cloud_stack.stack_name {{stack_id}} // import by numerical ID
terraform import grafana_cloud_stack.stack_name {{stack_slug}} // or import by slug
terraform import grafana_cloud_stack.name "{{ stackSlugOrID }}"
```
8 changes: 8 additions & 0 deletions docs/resources/cloud_stack_service_account.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,11 @@ resource "grafana_cloud_stack_service_account" "cloud_sa" {
### Read-Only

- `id` (String) The ID of this resource.

## Import

Import is supported using the following syntax:

```shell
terraform import grafana_cloud_stack_service_account.name "{{ stackSlug }}:{{ serviceAccountID }}"
```
3 changes: 1 addition & 2 deletions examples/resources/grafana_cloud_stack/import.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
terraform import grafana_cloud_stack.stack_name {{stack_id}} // import by numerical ID
terraform import grafana_cloud_stack.stack_name {{stack_slug}} // or import by slug
terraform import grafana_cloud_stack.name "{{ stackSlugOrID }}"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import grafana_cloud_stack_service_account.name "{{ stackSlug }}:{{ serviceAccountID }}"
32 changes: 24 additions & 8 deletions internal/resources/cloud/resource_cloud_stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const defaultReadinessTimeout = time.Minute * 5
var (
stackLabelRegex = regexp.MustCompile(`^[a-zA-Z0-9/\-.]+$`)
stackSlugRegex = regexp.MustCompile(`^[a-z][a-z0-9]+$`)
resourceStackID = common.NewResourceID("grafana_cloud_stack", common.StringIDField("stackSlugOrID"))
)

func resourceStack() *schema.Resource {
Expand Down Expand Up @@ -248,6 +249,11 @@ func createStack(ctx context.Context, d *schema.ResourceData, client *gcom.APICl
}

func updateStack(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
id, err := resourceStackID.Single(d.Id())
if err != nil {
return diag.FromErr(err)
}

// Default to the slug if the URL is not set
url := d.Get("url").(string)
if url == "" {
Expand All @@ -261,8 +267,8 @@ func updateStack(ctx context.Context, d *schema.ResourceData, client *gcom.APICl
Url: &url,
Labels: common.Ref(common.UnpackMap[string](d.Get("labels"))),
}
req := client.InstancesAPI.PostInstance(ctx, d.Id()).PostInstanceRequest(stack).XRequestId(ClientRequestID())
_, _, err := req.Execute()
req := client.InstancesAPI.PostInstance(ctx, id.(string)).PostInstanceRequest(stack).XRequestId(ClientRequestID())
_, _, err = req.Execute()
if err != nil {
return apiError(err)
}
Expand All @@ -275,13 +281,23 @@ func updateStack(ctx context.Context, d *schema.ResourceData, client *gcom.APICl
}

func deleteStack(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
req := client.InstancesAPI.DeleteInstance(ctx, d.Id()).XRequestId(ClientRequestID())
_, _, err := req.Execute()
id, err := resourceStackID.Single(d.Id())
if err != nil {
return diag.FromErr(err)
}

req := client.InstancesAPI.DeleteInstance(ctx, id.(string)).XRequestId(ClientRequestID())
_, _, err = req.Execute()
return apiError(err)
}

func readStack(ctx context.Context, d *schema.ResourceData, client *gcom.APIClient) diag.Diagnostics {
req := client.InstancesAPI.GetInstance(ctx, d.Id())
id, err := resourceStackID.Single(d.Id())
if err != nil {
return diag.FromErr(err)
}

req := client.InstancesAPI.GetInstance(ctx, id.(string))
stack, _, err := req.Execute()
if err, shouldReturn := common.CheckReadError("stack", d, err); shouldReturn {
return err
Expand All @@ -293,13 +309,13 @@ func readStack(ctx context.Context, d *schema.ResourceData, client *gcom.APIClie
return nil
}

connectionsReq := client.InstancesAPI.GetConnections(ctx, d.Id())
connectionsReq := client.InstancesAPI.GetConnections(ctx, id.(string))
connections, _, err := connectionsReq.Execute()
if err != nil {
return apiError(err)
}

if err := FlattenStack(d, stack, connections); err != nil {
if err := flattenStack(d, stack, connections); err != nil {
return diag.FromErr(err)
}
// Always set the wait attribute to true after creation
Expand All @@ -312,7 +328,7 @@ func readStack(ctx context.Context, d *schema.ResourceData, client *gcom.APIClie
return nil
}

func FlattenStack(d *schema.ResourceData, stack *gcom.FormattedApiInstance, connections *gcom.FormattedApiInstanceConnections) error {
func flattenStack(d *schema.ResourceData, stack *gcom.FormattedApiInstance, connections *gcom.FormattedApiInstanceConnections) error {
id := strconv.FormatInt(int64(stack.Id), 10)
d.SetId(id)
d.Set("name", stack.Name)
Expand Down
53 changes: 32 additions & 21 deletions internal/resources/cloud/resource_cloud_stack_service_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"net/url"
"strconv"
"time"

"github.com/grafana/grafana-com-public-clients/go/gcom"
Expand All @@ -17,6 +16,14 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

var (
resourceStackServiceAccountID = common.NewResourceID(
"grafana_cloud_stack_service_account",
common.StringIDField("stackSlug"),
common.IntIDField("serviceAccountID"),
)
)

func resourceStackServiceAccount() *schema.Resource {
return &schema.Resource{

Expand Down Expand Up @@ -70,7 +77,8 @@ Required access policy scopes:
}

func createStackServiceAccount(ctx context.Context, d *schema.ResourceData, cloudClient *gcom.APIClient) diag.Diagnostics {
client, cleanup, err := CreateTemporaryStackGrafanaClient(ctx, cloudClient, d.Get("stack_slug").(string), "terraform-temp-")
stackSlug := d.Get("stack_slug").(string)
client, cleanup, err := CreateTemporaryStackGrafanaClient(ctx, cloudClient, stackSlug, "terraform-temp-")
if err != nil {
return diag.FromErr(err)
}
Expand All @@ -87,27 +95,28 @@ func createStackServiceAccount(ctx context.Context, d *schema.ResourceData, clou
}
sa := resp.Payload

d.SetId(strconv.FormatInt(sa.ID, 10))
return readStackServiceAccountWithClient(client, d)
d.SetId(resourceStackServiceAccountID.Make(stackSlug, sa.ID))
return readStackServiceAccountWithClient(client, d, sa.ID)
}

func readStackServiceAccount(ctx context.Context, d *schema.ResourceData, cloudClient *gcom.APIClient) diag.Diagnostics {
client, cleanup, err := CreateTemporaryStackGrafanaClient(ctx, cloudClient, d.Get("stack_slug").(string), "terraform-temp-")
split, err := resourceStackServiceAccountID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
}
defer cleanup()
stackSlug, serviceAccountID := split[0].(string), split[1].(int64)

return readStackServiceAccountWithClient(client, d)
}

func readStackServiceAccountWithClient(client *goapi.GrafanaHTTPAPI, d *schema.ResourceData) diag.Diagnostics {
id, err := strconv.ParseInt(d.Id(), 10, 64)
client, cleanup, err := CreateTemporaryStackGrafanaClient(ctx, cloudClient, stackSlug, "terraform-temp-")
if err != nil {
return diag.FromErr(err)
}
defer cleanup()

resp, err := client.ServiceAccounts.RetrieveServiceAccount(id)
return readStackServiceAccountWithClient(client, d, serviceAccountID)
}

func readStackServiceAccountWithClient(client *goapi.GrafanaHTTPAPI, d *schema.ResourceData, serviceAccountID int64) diag.Diagnostics {
resp, err := client.ServiceAccounts.RetrieveServiceAccount(serviceAccountID)
if err != nil {
return diag.FromErr(err)
}
Expand All @@ -130,45 +139,47 @@ func readStackServiceAccountWithClient(client *goapi.GrafanaHTTPAPI, d *schema.R
}

func updateStackServiceAccount(ctx context.Context, d *schema.ResourceData, cloudClient *gcom.APIClient) diag.Diagnostics {
client, cleanup, err := CreateTemporaryStackGrafanaClient(ctx, cloudClient, d.Get("stack_slug").(string), "terraform-temp-")
split, err := resourceStackServiceAccountID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
}
defer cleanup()
stackSlug, serviceAccountID := split[0].(string), split[1].(int64)

id, err := strconv.ParseInt(d.Id(), 10, 64)
client, cleanup, err := CreateTemporaryStackGrafanaClient(ctx, cloudClient, stackSlug, "terraform-temp-")
if err != nil {
return diag.FromErr(err)
}
defer cleanup()

updateRequest := service_accounts.NewUpdateServiceAccountParams().
WithBody(&models.UpdateServiceAccountForm{
Name: d.Get("name").(string),
Role: d.Get("role").(string),
IsDisabled: d.Get("is_disabled").(bool),
}).
WithServiceAccountID(id)
WithServiceAccountID(serviceAccountID)

if _, err := client.ServiceAccounts.UpdateServiceAccount(updateRequest); err != nil {
return diag.FromErr(err)
}

return readStackServiceAccountWithClient(client, d)
return readStackServiceAccountWithClient(client, d, serviceAccountID)
}

func deleteStackServiceAccount(ctx context.Context, d *schema.ResourceData, cloudClient *gcom.APIClient) diag.Diagnostics {
client, cleanup, err := CreateTemporaryStackGrafanaClient(ctx, cloudClient, d.Get("stack_slug").(string), "terraform-temp-")
split, err := resourceStackServiceAccountID.Split(d.Id())
if err != nil {
return diag.FromErr(err)
}
defer cleanup()
stackSlug, serviceAccountID := split[0].(string), split[1].(int64)

id, err := strconv.ParseInt(d.Id(), 10, 64)
client, cleanup, err := CreateTemporaryStackGrafanaClient(ctx, cloudClient, stackSlug, "terraform-temp-")
if err != nil {
return diag.FromErr(err)
}
defer cleanup()

_, err = client.ServiceAccounts.DeleteServiceAccount(id)
_, err = client.ServiceAccounts.DeleteServiceAccount(serviceAccountID)
return diag.FromErr(err)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,11 @@ func stackServiceAccountTokenCreate(ctx context.Context, d *schema.ResourceData,
}
defer cleanup()

serviceAccountID, err := strconv.ParseInt(d.Get("service_account_id").(string), 10, 64)
split, err := resourceStackServiceAccountID.Split(d.Get("service_account_id").(string))
if err != nil {
return diag.FromErr(err)
}
serviceAccountID := split[1].(int64)

name := d.Get("name").(string)
ttl := d.Get("seconds_to_live").(int)
Expand Down Expand Up @@ -115,10 +116,11 @@ func stackServiceAccountTokenRead(ctx context.Context, d *schema.ResourceData, c
}

func stackServiceAccountTokenReadWithClient(c *goapi.GrafanaHTTPAPI, d *schema.ResourceData) diag.Diagnostics {
serviceAccountID, err := strconv.ParseInt(d.Get("service_account_id").(string), 10, 64)
split, err := resourceStackServiceAccountID.Split(d.Get("service_account_id").(string))
if err != nil {
return diag.FromErr(err)
}
serviceAccountID := split[1].(int64)

response, err := c.ServiceAccounts.ListTokens(serviceAccountID)
if err != nil {
Expand Down Expand Up @@ -161,10 +163,11 @@ func stackServiceAccountTokenDelete(ctx context.Context, d *schema.ResourceData,
}
defer cleanup()

serviceAccountID, err := strconv.ParseInt(d.Get("service_account_id").(string), 10, 64)
split, err := resourceStackServiceAccountID.Split(d.Get("service_account_id").(string))
if err != nil {
return diag.FromErr(err)
}
serviceAccountID := split[1].(int64)

id, err := strconv.ParseInt(d.Id(), 10, 32)
if err != nil {
Expand Down

0 comments on commit c8ac63a

Please sign in to comment.