-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
New resource: aws_grafana_workspace_api_key
#25286
Changes from all commits
ca238f0
11a37b9
4afdc5b
a305e0b
f495674
849759a
aa5c4b2
73cff8d
6b6f3bd
0280b59
1d633de
73acdc3
67ae57d
eef5fc6
6782ffc
662197c
dc1c31f
e10eb39
3e32805
d71728b
00e65e8
4be49dd
8c75558
493888a
340061d
ddaec83
246ce9b
5ab5cfe
3fe1fec
6f4f7ce
61230a4
9ba1c43
f286d65
6ca17f1
d3cc2df
54da3d1
f8539cd
18141b5
00bf390
1df13f7
54e75f0
f80724a
fb84a4f
de8f06b
3e1d76e
0fd72f5
8d9b427
9422d22
8442338
29bb6be
c38010e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:new-resource | ||
aws_grafana_workspace_api_key | ||
``` |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,124 @@ | ||||||
package grafana | ||||||
|
||||||
import ( | ||||||
"fmt" | ||||||
"log" | ||||||
"strings" | ||||||
|
||||||
"github.com/aws/aws-sdk-go/aws" | ||||||
"github.com/aws/aws-sdk-go/service/managedgrafana" | ||||||
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" | ||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||||||
"github.com/hashicorp/terraform-provider-aws/internal/conns" | ||||||
) | ||||||
|
||||||
func ResourceWorkspaceAPIKey() *schema.Resource { | ||||||
return &schema.Resource{ | ||||||
Create: resourceWorkspaceAPIKeyCreate, | ||||||
Read: schema.Noop, | ||||||
Update: schema.Noop, | ||||||
Delete: resourceWorkspaceAPIKeyDelete, | ||||||
|
||||||
Schema: map[string]*schema.Schema{ | ||||||
"key": { | ||||||
Type: schema.TypeString, | ||||||
Computed: true, | ||||||
}, | ||||||
"key_name": { | ||||||
Type: schema.TypeString, | ||||||
Required: true, | ||||||
ForceNew: true, | ||||||
ValidateFunc: validation.StringLenBetween(1, 100), | ||||||
}, | ||||||
"key_role": { | ||||||
Type: schema.TypeString, | ||||||
Required: true, | ||||||
ForceNew: true, | ||||||
ValidateFunc: validation.StringInSlice(managedgrafana.Role_Values(), false), | ||||||
}, | ||||||
"seconds_to_live": { | ||||||
Type: schema.TypeInt, | ||||||
Required: true, | ||||||
ValidateFunc: validation.IntBetween(1, 2592000), | ||||||
}, | ||||||
"workspace_id": { | ||||||
Type: schema.TypeString, | ||||||
Required: true, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add validation that matches the API documentation. Would recommend including a regex to verify the format if possible. I know the other resources in grafana don't include it. And it is not required since users will most likely be using a reference to a resource.id and not typing it in.
|
||||||
ForceNew: true, | ||||||
}, | ||||||
}, | ||||||
} | ||||||
} | ||||||
|
||||||
func resourceWorkspaceAPIKeyCreate(d *schema.ResourceData, meta interface{}) error { | ||||||
conn := meta.(*conns.AWSClient).GrafanaConn | ||||||
|
||||||
keyName := d.Get("key_name").(string) | ||||||
workspaceID := d.Get("workspace_id").(string) | ||||||
id := WorkspaceAPIKeyCreateResourceID(workspaceID, keyName) | ||||||
input := &managedgrafana.CreateWorkspaceApiKeyInput{ | ||||||
KeyName: aws.String(keyName), | ||||||
KeyRole: aws.String(d.Get("key_role").(string)), | ||||||
SecondsToLive: aws.Int64(int64(d.Get("seconds_to_live").(int))), | ||||||
WorkspaceId: aws.String(workspaceID), | ||||||
} | ||||||
|
||||||
log.Printf("[DEBUG] Creating Grafana Workspace API Key: %s", input) | ||||||
output, err := conn.CreateWorkspaceApiKey(input) | ||||||
|
||||||
if err != nil { | ||||||
return fmt.Errorf("creating Grafana Workspace API Key (%s): %w", id, err) | ||||||
} | ||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Set Id after the response error check. I believe that a grafana workspace instance supports multiple API keys, each with different names? If this is true (please verify with the service team), the Id for this resource should be a composite Id. There is an example of a composite key.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checked with the Service team and they mentioned that a Single Grafana Workspace can have multiple API keys and incorporated the changes as requested. |
||||||
d.SetId(id) | ||||||
d.Set("key", output.Key) | ||||||
|
||||||
return nil | ||||||
} | ||||||
|
||||||
func resourceWorkspaceAPIKeyDelete(d *schema.ResourceData, meta interface{}) error { | ||||||
conn := meta.(*conns.AWSClient).GrafanaConn | ||||||
|
||||||
workspaceID, keyName, error := WorkspaceAPIKeyParseResourceID(d.Id()) | ||||||
|
||||||
if error != nil { | ||||||
return error | ||||||
} | ||||||
|
||||||
log.Printf("[DEBUG] Deleting Grafana Workspace API Key: %s", d.Id()) | ||||||
_, err := conn.DeleteWorkspaceApiKey(&managedgrafana.DeleteWorkspaceApiKeyInput{ | ||||||
KeyName: aws.String(keyName), | ||||||
WorkspaceId: aws.String(workspaceID), | ||||||
}) | ||||||
|
||||||
if tfawserr.ErrCodeEquals(err, managedgrafana.ErrCodeResourceNotFoundException) { | ||||||
return nil | ||||||
} | ||||||
|
||||||
if err != nil { | ||||||
return fmt.Errorf("deleting Grafana Workspace API Key (%s): %w", d.Id(), err) | ||||||
} | ||||||
|
||||||
return nil | ||||||
|
||||||
} | ||||||
|
||||||
const workspaceAPIKeyIDSeparator = "/" | ||||||
|
||||||
func WorkspaceAPIKeyCreateResourceID(workspaceID, keyName string) string { | ||||||
parts := []string{workspaceID, keyName} | ||||||
id := strings.Join(parts, workspaceAPIKeyIDSeparator) | ||||||
|
||||||
return id | ||||||
} | ||||||
|
||||||
func WorkspaceAPIKeyParseResourceID(id string) (string, string, error) { | ||||||
parts := strings.Split(id, workspaceAPIKeyIDSeparator) | ||||||
|
||||||
if len(parts) != 2 || parts[0] == "" || parts[1] == "" { | ||||||
return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected workspace-id%[2]skey-name", id, workspaceAPIKeyIDSeparator) | ||||||
} | ||||||
|
||||||
return parts[0], parts[1], nil | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package grafana_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/service/managedgrafana" | ||
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/hashicorp/terraform-provider-aws/internal/acctest" | ||
) | ||
|
||
func testAccWorkspaceAPIKey_basic(t *testing.T) { | ||
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) | ||
resourceName := "aws_grafana_workspace_api_key.test" | ||
workspaceResourceName := "aws_grafana_workspace.test" | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { acctest.PreCheck(t); acctest.PreCheckPartitionHasService(managedgrafana.EndpointsID, t) }, | ||
ErrorCheck: acctest.ErrorCheck(t, managedgrafana.EndpointsID), | ||
CheckDestroy: acctest.CheckDestroyNoop, | ||
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccWorkspaceAPIKeyConfig_basic(rName), | ||
Check: resource.ComposeAggregateTestCheckFunc( | ||
resource.TestCheckResourceAttrSet(resourceName, "key"), | ||
resource.TestCheckResourceAttr(resourceName, "key_name", rName), | ||
resource.TestCheckResourceAttr(resourceName, "key_role", managedgrafana.RoleEditor), | ||
resource.TestCheckResourceAttr(resourceName, "seconds_to_live", "3600"), | ||
resource.TestCheckResourceAttrPair(resourceName, "workspace_id", workspaceResourceName, "id"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add an evaluation of the requested There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added as requested. |
||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccWorkspaceAPIKeyConfig_basic(rName string) string { | ||
return fmt.Sprintf(` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unnecessary use of return fmt.Sprintf(, as no strings are being formatted/interpolated. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed. |
||
resource "aws_iam_role" "test" { | ||
name = %[1]q | ||
|
||
assume_role_policy = jsonencode({ | ||
Version = "2012-10-17" | ||
Statement = [ | ||
{ | ||
Action = "sts:AssumeRole" | ||
Effect = "Allow" | ||
Sid = "" | ||
Principal = { | ||
Service = "grafana.amazonaws.com" | ||
} | ||
}, | ||
] | ||
}) | ||
} | ||
|
||
resource "aws_grafana_workspace" "test" { | ||
account_access_type = "CURRENT_ACCOUNT" | ||
authentication_providers = ["SAML"] | ||
permission_type = "SERVICE_MANAGED" | ||
role_arn = aws_iam_role.test.arn | ||
} | ||
|
||
resource "aws_grafana_workspace_api_key" "test" { | ||
key_name = %[1]q | ||
key_role = "EDITOR" | ||
seconds_to_live = 3600 | ||
workspace_id = aws_grafana_workspace.test.id | ||
} | ||
`, rName) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--- | ||
subcategory: "Managed Grafana" | ||
layout: "aws" | ||
page_title: "AWS: aws_grafana_workspace_api_key" | ||
description: |- | ||
Creates a Grafana API key for the workspace. This key can be used to authenticate requests sent to the workspace's HTTP API. | ||
--- | ||
|
||
# Resource: aws_grafana_workspace_api_key | ||
|
||
Provides an Amazon Managed Grafana workspace API Key resource. | ||
|
||
## Example Usage | ||
|
||
### Basic configuration | ||
|
||
```terraform | ||
resource "aws_grafana_workspace_api_key" "key" { | ||
key_name = "test-key" | ||
key_role = "VIEWER" | ||
seconds_to_live = 3600 | ||
workspace_id = aws_grafana_workspace.test.id | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are required: | ||
|
||
- `key_name` - (Required) Specifies the name of the API key. Key names must be unique to the workspace. | ||
- `key_role` - (Required) Specifies the permission level of the API key. Valid values are `VIEWER`, `EDITOR`, or `ADMIN`. | ||
- `seconds_to_live` - (Required) Specifies the time in seconds until the API key expires. Keys can be valid for up to 30 days. | ||
- `workspace_id` - (Required) The ID of the workspace that the API key is valid for. | ||
|
||
## Attributes Reference | ||
|
||
In addition to all arguments above, the following attributes are exported: | ||
|
||
* `key` - The key token in JSON format. Use this value as a bearer token to authenticate HTTP requests to the workspace. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not see how this value is exported as the Please verify? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please include a Key attribute to expose the response element
Key
. The Key is a token, and the value is to be used as a bearer token to authenticate HTTP requests to the workspace.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added Key in the Resource Structure.