@@ -2,6 +2,7 @@ package cloud_test
22
33import (
44 "context"
5+ "errors"
56 "fmt"
67 "os"
78 "strconv"
@@ -18,20 +19,19 @@ import (
1819 "github.com/grafana/terraform-provider-grafana/v4/internal/testutils"
1920)
2021
21- // This test covers both the cloud_access_policy and cloud_access_policy_rotating_token resources.
2222func TestResourceAccessPolicyRotatingToken_Basic (t * testing.T ) {
2323 t .Parallel ()
2424 testutils .CheckCloudAPITestsEnabled (t )
2525
2626 var policy gcom.AuthAccessPolicy
2727 var policyToken gcom.AuthToken
28- var policyToken2 gcom.AuthToken
28+ var policyTokenAfterRecreation gcom.AuthToken
2929
3030 rotateAfter := time .Now ().Add (time .Hour * 2 ).UTC ()
31- updatedRotateAfter := time . Now (). Add (time .Hour * 4 ). UTC ( )
31+ updatedRotateAfter := rotateAfter . Add (time .Hour * 4 )
3232 postRotationLifetime := "24h"
33- namePrefix := "test-rotating-token-terraform"
3433 expectedExpiresAt := rotateAfter .Add (24 * time .Hour ).Format (time .RFC3339 )
34+ namePrefix := "test-rotating-token-terraform"
3535 expectedName := fmt .Sprintf ("%s-%d-%s" , namePrefix , rotateAfter .Unix (), postRotationLifetime )
3636 accessPolicyName := fmt .Sprintf ("test-rotating-token-terraform-initial-%s" , acctest .RandStringFromCharSet (6 , acctest .CharSetAlpha ))
3737
@@ -40,7 +40,7 @@ func TestResourceAccessPolicyRotatingToken_Basic(t *testing.T) {
4040 CheckDestroy : resource .ComposeTestCheckFunc (
4141 testAccCloudAccessPolicyCheckDestroy ("prod-us-east-0" , & policy ),
4242 testAccCloudAccessPolicyTokenCheckDestroy ("prod-us-east-0" , & policyToken ),
43- testAccCloudAccessPolicyTokenCheckDestroy ("prod-us-east-0" , & policyToken2 ),
43+ testAccCloudAccessPolicyTokenCheckDestroy ("prod-us-east-0" , & policyTokenAfterRecreation ),
4444 ),
4545 Steps : []resource.TestStep {
4646 // Test that the cloud access policy and rotating token get created
@@ -79,32 +79,7 @@ func TestResourceAccessPolicyRotatingToken_Basic(t *testing.T) {
7979 resource .TestCheckResourceAttr ("grafana_cloud_access_policy_rotating_token.test" , "region" , "prod-us-east-0" ),
8080 ),
8181 },
82- // Test that the token exists and can be manually deleted through the API
83- {
84- Config : testAccCloudAccessPolicyRotatingTokenConfigBasic (accessPolicyName , "" , "prod-us-east-0" , namePrefix , rotateAfter .Unix (), postRotationLifetime ),
85- PreConfig : func () {
86- orgID , err := strconv .ParseInt (* policy .OrgId , 10 , 32 )
87- if err != nil {
88- t .Fatal (err )
89- }
90- client := testutils .Provider .Meta ().(* common.Client ).GrafanaCloudAPI
91- _ , _ , err = client .TokensAPI .DeleteToken (context .Background (), * policyToken .Id ).
92- Region ("prod-us-east-0" ).
93- OrgId (int32 (orgID )).
94- XRequestId ("deleting-token" ).Execute ()
95- if err != nil {
96- t .Fatalf ("error getting cloud access policy: %s" , err )
97- }
98- },
99- },
100- // Recreate token because it got deleted in the last test
101- {
102- Config : testAccCloudAccessPolicyRotatingTokenConfigBasic (accessPolicyName , "updated" , "prod-us-east-0" , namePrefix , rotateAfter .Unix (), postRotationLifetime ),
103- Check : resource .ComposeTestCheckFunc (
104- testAccCloudAccessPolicyCheckExists ("grafana_cloud_access_policy.rotating_token_test" , & policy ),
105- testAccCloudAccessPolicyTokenCheckExists ("grafana_cloud_access_policy_rotating_token.test" , & policyToken ),
106- ),
107- },
82+ // Test import
10883 {
10984 ResourceName : "grafana_cloud_access_policy_rotating_token.test" ,
11085 ImportState : true ,
@@ -116,56 +91,81 @@ func TestResourceAccessPolicyRotatingToken_Basic(t *testing.T) {
11691 Config : testAccCloudAccessPolicyRotatingTokenConfigBasic (accessPolicyName , "" , "prod-us-east-0" , namePrefix , updatedRotateAfter .Unix (), postRotationLifetime ),
11792 Check : resource .ComposeTestCheckFunc (
11893 testAccCloudAccessPolicyCheckExists ("grafana_cloud_access_policy.rotating_token_test" , & policy ),
119- testAccCloudAccessPolicyTokenCheckExists ("grafana_cloud_access_policy_rotating_token.test" , & policyToken2 ),
94+ testAccCloudAccessPolicyTokenCheckExists ("grafana_cloud_access_policy_rotating_token.test" , & policyTokenAfterRecreation ),
12095 resource .TestCheckResourceAttr ("grafana_cloud_access_policy_rotating_token.test" , "rotate_after" , strconv .Itoa (int (updatedRotateAfter .Unix ()))),
121- // Verify the token ID changed (indicating recreation)
12296 func (s * terraform.State ) error {
123- if policyToken .Id == nil || policyToken2 .Id == nil {
97+ if policyToken .Id == nil || policyTokenAfterRecreation .Id == nil {
12498 return fmt .Errorf ("expected token to be recreated, but ID is nil" )
12599 }
126- if * policyToken .Id == * policyToken2 .Id {
100+ if * policyToken .Id == * policyTokenAfterRecreation .Id {
127101 return fmt .Errorf ("expected token to be recreated, but ID remained the same: %s" , * policyToken .Id )
128102 }
129103 return nil
130104 },
131105 ),
132106 },
133- // Test import with different values in config vs what is inferred from the name
107+ // Make sure token exists
134108 {
135- Config : testAccCloudAccessPolicyRotatingTokenConfigMismatch (accessPolicyName , "" , "prod-us-east-0" , "different-prefix" , time .Now ().Add (time .Hour * 6 ).Unix (), "12h" ),
136- ResourceName : "grafana_cloud_access_policy_rotating_token.test" ,
137- ImportState : true ,
138- ImportStateVerify : false , // We expect this to fail verification
139- ImportStateCheck : func (s []* terraform.InstanceState ) error {
140- if len (s ) != 1 {
141- return fmt .Errorf ("expected 1 state, got %d" , len (s ))
142- }
143-
144- state := s [0 ]
109+ Config : testAccCloudAccessPolicyRotatingTokenConfigBasic (accessPolicyName , "" , "prod-us-east-0" , "test-no-delete" , rotateAfter .Unix (), postRotationLifetime ),
110+ Check : resource .ComposeTestCheckFunc (
111+ testAccCloudAccessPolicyCheckExists ("grafana_cloud_access_policy.rotating_token_test" , & policy ),
112+ testAccCloudAccessPolicyTokenCheckExists ("grafana_cloud_access_policy_rotating_token.test" , & policyToken ),
113+ ),
114+ },
115+ // Test that destroy does not actually delete the token (it should only show a warning instead)
116+ {
117+ Config : testAccCloudAccessPolicyRotatingTokenConfigNoToken (accessPolicyName , "" , "prod-us-east-0" ),
118+ Check : resource .ComposeTestCheckFunc (
119+ testAccCloudAccessPolicyCheckExists ("grafana_cloud_access_policy.rotating_token_test" , & policy ),
120+ func (s * terraform.State ) error {
121+ // Verify token still exists in Grafana Cloud API
122+ client := testutils .Provider .Meta ().(* common.Client ).GrafanaCloudAPI
123+ orgID , err := strconv .ParseInt (* policy .OrgId , 10 , 32 )
124+ if err != nil {
125+ return err
126+ }
127+ token , _ , err := client .TokensAPI .GetToken (context .Background (), * policyToken .Id ).
128+ Region ("prod-us-east-0" ).
129+ OrgId (int32 (orgID )).
130+ Execute ()
131+ if err != nil {
132+ return fmt .Errorf ("expected token to still exist after destroy, but API call failed: %s" , err )
133+ }
134+ if token == nil || token .Id == nil || policyToken .Id == nil {
135+ return errors .New ("expected token to still exist after destroy, but API response is empty" )
136+ }
137+ if * token .Id != * policyToken .Id {
138+ return fmt .Errorf ("expected token IDs to be the same (%s) (%s)" , * token .Id , * policyToken .Id )
139+ }
145140
146- // Verify that imported values come from the token name in Grafana Cloud, not the Terraform state we had
147- if state .Attributes ["name_prefix" ] != namePrefix {
148- return fmt .Errorf ("expected name_prefix to be inferred as %s from token name, got %s" , namePrefix , state .Attributes ["name_prefix" ])
149- }
141+ // Check that the token resource is no longer in state
142+ _ , exists := s .RootModule ().Resources ["grafana_cloud_access_policy_rotating_token.test" ]
143+ if exists {
144+ return fmt .Errorf ("expected token resource to be removed from state after destroy, but it still exists" )
145+ }
150146
151- if state .Attributes ["rotate_after" ] != strconv .Itoa (int (updatedRotateAfter .Unix ())) {
152- return fmt .Errorf ("expected rotate_after to be inferred as %s from token name, got %s" , strconv .Itoa (int (updatedRotateAfter .Unix ())), state .Attributes ["rotate_after" ])
147+ return nil
148+ },
149+ ),
150+ },
151+ // Test that the token exists and can be manually deleted through the API
152+ {
153+ Config : testAccCloudAccessPolicyRotatingTokenConfigNoToken (accessPolicyName , "" , "prod-us-east-0" ),
154+ PreConfig : func () {
155+ orgID , err := strconv .ParseInt (* policy .OrgId , 10 , 32 )
156+ if err != nil {
157+ t .Fatal (err )
153158 }
154-
155- if state .Attributes ["post_rotation_lifetime" ] != postRotationLifetime {
156- return fmt .Errorf ("expected post_rotation_lifetime to be inferred as %s from token name, got %s" , postRotationLifetime , state .Attributes ["post_rotation_lifetime" ])
159+ client := testutils .Provider .Meta ().(* common.Client ).GrafanaCloudAPI
160+ _ , _ , err = client .TokensAPI .DeleteToken (context .Background (), * policyToken .Id ).
161+ Region ("prod-us-east-0" ).
162+ OrgId (int32 (orgID )).
163+ XRequestId ("deleting-token" ).Execute ()
164+ if err != nil {
165+ t .Fatalf ("error getting cloud access policy: %s" , err )
157166 }
158-
159- return nil
160167 },
161168 },
162- // Test that destroy does not actually delete the token (it should only show a warning instead)
163- {
164- Config : testAccCloudAccessPolicyRotatingTokenConfigBasic (accessPolicyName , "" , "prod-us-east-0" , "test-no-delete" , rotateAfter .Unix (), postRotationLifetime ),
165- Destroy : true ,
166- // The plan should be empty since rotating tokens do not get deleted
167- ExpectNonEmptyPlan : false ,
168- },
169169 },
170170 })
171171}
@@ -217,6 +217,44 @@ func testAccCloudAccessPolicyRotatingTokenConfigBasic(name, displayName, region
217217 ` , name , displayName , strings .Join (scopes , `","` ), os .Getenv ("GRAFANA_CLOUD_ORG" ), namePrefix , rotateAfter , region , postRotationLifetime )
218218}
219219
220+ func testAccCloudAccessPolicyRotatingTokenConfigNoToken (name , displayName , region string ) string {
221+ if displayName != "" {
222+ displayName = fmt .Sprintf ("display_name = \" %s\" " , displayName )
223+ }
224+
225+ scopes := []string {
226+ "metrics:read" ,
227+ "logs:write" ,
228+ "accesspolicies:read" ,
229+ "accesspolicies:write" ,
230+ "accesspolicies:delete" ,
231+ "datadog:validate" ,
232+ }
233+
234+ return fmt .Sprintf (`
235+ data "grafana_cloud_organization" "current" {
236+ slug = "%[4]s"
237+ }
238+
239+ resource "grafana_cloud_access_policy" "rotating_token_test" {
240+ region = "%[5]s"
241+ name = "%[1]s"
242+ %[2]s
243+
244+ scopes = ["%[3]s"]
245+
246+ realm {
247+ type = "org"
248+ identifier = data.grafana_cloud_organization.current.id
249+
250+ label_policy {
251+ selector = "{namespace=\"default\"}"
252+ }
253+ }
254+ }
255+ ` , name , displayName , strings .Join (scopes , `","` ), os .Getenv ("GRAFANA_CLOUD_ORG" ), region )
256+ }
257+
220258func testAccCloudAccessPolicyRotatingTokenConfigMismatch (name , displayName , region string , namePrefix string , rotateAfter int64 , postRotationLifetime string ) string {
221259 if displayName != "" {
222260 displayName = fmt .Sprintf ("display_name = \" %s\" " , displayName )
0 commit comments