Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloud: Make full use of ID + import generation framework #1412

Merged
merged 1 commit into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading