Skip to content

Commit

Permalink
Cloud Resources: Use OpenAPI client for tests
Browse files Browse the repository at this point in the history
  • Loading branch information
julienduchesne committed Jan 30, 2024
1 parent 1f39c66 commit 2dea0fe
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 116 deletions.
4 changes: 2 additions & 2 deletions internal/resources/cloud/data_source_cloud_stack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"testing"

gapi "github.com/grafana/grafana-api-golang-client"
"github.com/grafana/grafana-com-public-clients/go/gcom"
"github.com/grafana/terraform-provider-grafana/internal/testutils"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)
Expand All @@ -15,7 +15,7 @@ func TestAccDataSourceStack_Basic(t *testing.T) {
prefix := "tfdatatest"

resourceName := GetRandomStackName(prefix)
var stack gapi.Stack
var stack gcom.FormattedApiInstance
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccDeleteExistingStacks(t, prefix)
Expand Down
2 changes: 1 addition & 1 deletion internal/resources/cloud/request_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cloud

import "github.com/hashicorp/go-uuid"

func clientRequestID() string {
func ClientRequestID() string {
uuid, err := uuid.GenerateUUID()
if err != nil {
return ""
Expand Down
4 changes: 2 additions & 2 deletions internal/resources/cloud/resource_cloud_api_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func ResourceAPIKeyCreate(ctx context.Context, d *schema.ResourceData, meta inte

resp, _, err := c.OrgsAPI.PostApiKeys(ctx, org).
PostApiKeysRequest(req).
XRequestId(clientRequestID()).
XRequestId(ClientRequestID()).
Execute()
if err != nil {
return diag.FromErr(err)
Expand Down Expand Up @@ -103,7 +103,7 @@ func ResourceAPIKeyRead(ctx context.Context, d *schema.ResourceData, meta interf
func ResourceAPIKeyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c := meta.(*common.Client).GrafanaCloudAPIOpenAPI

_, err := c.OrgsAPI.DelApiKey(ctx, d.Get("name").(string), d.Get("cloud_org_slug").(string)).XRequestId(clientRequestID()).Execute()
_, err := c.OrgsAPI.DelApiKey(ctx, d.Get("name").(string), d.Get("cloud_org_slug").(string)).XRequestId(ClientRequestID()).Execute()
d.SetId("")
return diag.FromErr(err)
}
56 changes: 18 additions & 38 deletions internal/resources/cloud/resource_cloud_api_key_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package cloud_test

import (
"context"
"fmt"
"os"
"strings"
"testing"

"github.com/grafana/terraform-provider-grafana/internal/common"
"github.com/grafana/terraform-provider-grafana/internal/resources/cloud"
"github.com/grafana/terraform-provider-grafana/internal/testutils"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand Down Expand Up @@ -35,12 +37,12 @@ func TestAccCloudApiKey_Basic(t *testing.T) {

resource.ParallelTest(t, resource.TestCase{
ProviderFactories: testutils.ProviderFactories,
CheckDestroy: testAccCheckCloudAPIKeyDestroy,
CheckDestroy: testAccCheckCloudAPIKeyDestroy(resourceName),
Steps: []resource.TestStep{
{
Config: testAccCloudAPIKeyConfig(resourceName, tt.role),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudAPIKeyExists("grafana_cloud_api_key.test"),
testAccCheckCloudAPIKeyExists(resourceName),
resource.TestCheckResourceAttrSet("grafana_cloud_api_key.test", "id"),
resource.TestCheckResourceAttrSet("grafana_cloud_api_key.test", "key"),
resource.TestCheckResourceAttr("grafana_cloud_api_key.test", "name", resourceName),
Expand All @@ -59,67 +61,45 @@ func TestAccCloudApiKey_Basic(t *testing.T) {
}
}

func testAccCheckCloudAPIKeyExists(resourceName string) resource.TestCheckFunc {
func testAccCheckCloudAPIKeyExists(apiKeyName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("resource `%s` not found", resourceName)
}

if rs.Primary.ID == "" {
return fmt.Errorf("resource `%s` has no ID set", resourceName)
}

client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI
res, err := client.ListCloudAPIKeys(rs.Primary.Attributes["cloud_org_slug"])
client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPIOpenAPI
res, _, err := client.OrgsAPI.GetApiKeys(context.Background(), os.Getenv("GRAFANA_CLOUD_ORG")).Execute()
if err != nil {
return err
}

for _, apiKey := range res.Items {
if apiKey.Name == rs.Primary.Attributes["name"] {
if apiKey.Name == apiKeyName {
return nil
}
}

return fmt.Errorf("resource `%s` not found via API", resourceName)
return fmt.Errorf("API Key `%s` not found via API", apiKeyName)
}
}

func testAccCheckCloudAPIKeyDestroy(s *terraform.State) error {
client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI

for name, rs := range s.RootModule().Resources {
if rs.Type != "grafana_cloud_api_key" {
continue
}

res, err := client.ListCloudAPIKeys(rs.Primary.Attributes["cloud_org_slug"])
if err != nil {
return err
}

for _, apiKey := range res.Items {
if apiKey.Name == rs.Primary.Attributes["name"] {
return fmt.Errorf("resource `%s` still exists via API", name)
}
func testAccCheckCloudAPIKeyDestroy(apiKeyName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
getErr := testAccCheckCloudAPIKeyExists(apiKeyName)(s)
if getErr == nil {
return fmt.Errorf("API Key `%s` still exists via API", apiKeyName)
}
return nil
}

return nil
}

func testAccDeleteExistingCloudAPIKeys(t *testing.T, prefix string) {
org := os.Getenv("GRAFANA_CLOUD_ORG")
client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI
resp, err := client.ListCloudAPIKeys(org)
client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPIOpenAPI
resp, _, err := client.OrgsAPI.GetApiKeys(context.Background(), org).Execute()
if err != nil {
t.Error(err)
}

for _, key := range resp.Items {
if strings.HasPrefix(key.Name, prefix) {
err := client.DeleteCloudAPIKey(org, key.Name)
_, err := client.OrgsAPI.DelApiKey(context.Background(), org, key.Name).XRequestId(cloud.ClientRequestID()).Execute()
if err != nil {
t.Error(err)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/resources/cloud/resource_cloud_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func ResourcePluginInstallationCreate(ctx context.Context, d *schema.ResourceDat
}
_, _, err := client.InstancesAPI.PostInstancePlugins(ctx, stackSlug).
PostInstancePluginsRequest(req).
XRequestId(clientRequestID()).Execute()
XRequestId(ClientRequestID()).Execute()
if err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -93,6 +93,6 @@ func ResourcePluginInstallationDelete(ctx context.Context, d *schema.ResourceDat
splitID := strings.SplitN(d.Id(), "_", 2)
stackSlug, pluginSlug := splitID[0], splitID[1]

_, _, err := client.InstancesAPI.DeleteInstancePlugin(ctx, stackSlug, pluginSlug).XRequestId(clientRequestID()).Execute()
_, _, err := client.InstancesAPI.DeleteInstancePlugin(ctx, stackSlug, pluginSlug).XRequestId(ClientRequestID()).Execute()
return diag.FromErr(err)
}
9 changes: 5 additions & 4 deletions internal/resources/cloud/resource_cloud_plugin_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package cloud_test

import (
"context"
"fmt"
"testing"

gapi "github.com/grafana/grafana-api-golang-client"
"github.com/grafana/grafana-com-public-clients/go/gcom"
"github.com/grafana/terraform-provider-grafana/internal/common"
"github.com/grafana/terraform-provider-grafana/internal/testutils"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand All @@ -14,7 +15,7 @@ import (
func TestAccResourcePluginInstallation(t *testing.T) {
testutils.CheckCloudAPITestsEnabled(t)

var stack gapi.Stack
var stack gcom.FormattedApiInstance
stackPrefix := "tfplugin"
stackSlug := GetRandomStackName(stackPrefix)
pluginSlug := "aws-datasource-provisioner-app"
Expand Down Expand Up @@ -54,8 +55,8 @@ func TestAccResourcePluginInstallation(t *testing.T) {

func testAccCloudPluginInstallationCheckExists(stackSlug string, pluginSlug string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI
_, err := client.GetCloudPluginInstallation(stackSlug, pluginSlug)
client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPIOpenAPI
_, _, err := client.InstancesAPI.GetInstancePlugin(context.Background(), stackSlug, pluginSlug).Execute()
if err != nil {
return fmt.Errorf("error getting installation: %s", err)
}
Expand Down
6 changes: 3 additions & 3 deletions internal/resources/cloud/resource_cloud_stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func CreateStack(ctx context.Context, d *schema.ResourceData, meta interface{})
}

err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
req := client.InstancesAPI.PostInstances(ctx).PostInstancesRequest(stack).XRequestId(clientRequestID())
req := client.InstancesAPI.PostInstances(ctx).PostInstancesRequest(stack).XRequestId(ClientRequestID())
createdStack, _, err := req.Execute()
switch {
case err != nil && strings.Contains(strings.ToLower(err.Error()), "conflict"):
Expand Down Expand Up @@ -313,7 +313,7 @@ func UpdateStack(ctx context.Context, d *schema.ResourceData, meta interface{})
Slug: common.Ref(d.Get("slug").(string)),
Description: common.Ref(d.Get("description").(string)),
}
req := client.InstancesAPI.PostInstance(ctx, d.Id()).PostInstanceRequest(stack).XRequestId(clientRequestID())
req := client.InstancesAPI.PostInstance(ctx, d.Id()).PostInstanceRequest(stack).XRequestId(ClientRequestID())
_, _, err := req.Execute()
if err != nil {
return diag.FromErr(err)
Expand All @@ -329,7 +329,7 @@ func UpdateStack(ctx context.Context, d *schema.ResourceData, meta interface{})

func DeleteStack(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPIOpenAPI
req := client.InstancesAPI.DeleteInstance(ctx, d.Id()).XRequestId(clientRequestID())
req := client.InstancesAPI.DeleteInstance(ctx, d.Id()).XRequestId(ClientRequestID())
_, _, err := req.Execute()
return diag.FromErr(err)
}
Expand Down
102 changes: 85 additions & 17 deletions internal/resources/cloud/resource_cloud_stack_api_key_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package cloud_test

import (
"errors"
"context"
"fmt"
"net/url"
"strings"
"testing"
"time"

gapi "github.com/grafana/grafana-api-golang-client"
"github.com/grafana/grafana-com-public-clients/go/gcom"
goapi "github.com/grafana/grafana-openapi-client-go/client"
"github.com/grafana/grafana-openapi-client-go/client/api_keys"
"github.com/grafana/terraform-provider-grafana/internal/common"
"github.com/grafana/terraform-provider-grafana/internal/resources/cloud"
"github.com/grafana/terraform-provider-grafana/internal/testutils"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
Expand All @@ -17,7 +21,7 @@ import (
func TestAccGrafanaAuthKeyFromCloud(t *testing.T) {
testutils.CheckCloudAPITestsEnabled(t)

var stack gapi.Stack
var stack gcom.FormattedApiInstance
prefix := "tfapikeytest"
slug := GetRandomStackName(prefix)

Expand All @@ -32,6 +36,7 @@ func TestAccGrafanaAuthKeyFromCloud(t *testing.T) {
Config: testAccGrafanaAuthKeyFromCloud(slug, slug),
Check: resource.ComposeTestCheckFunc(
testAccStackCheckExists("grafana_cloud_stack.test", &stack),
testAccGrafanaAuthCheckKeys(&stack, []string{"management-key"}),
resource.TestCheckResourceAttrSet("grafana_cloud_stack_api_key.management", "key"),
resource.TestCheckResourceAttr("grafana_cloud_stack_api_key.management", "name", "management-key"),
resource.TestCheckResourceAttr("grafana_cloud_stack_api_key.management", "role", "Admin"),
Expand All @@ -40,7 +45,7 @@ func TestAccGrafanaAuthKeyFromCloud(t *testing.T) {
},
{
Config: testAccStackConfigBasic(slug, slug),
Check: testAccGrafanaAuthKeyCheckDestroyCloud,
Check: testAccGrafanaAuthCheckKeys(&stack, []string{}),
},
},
})
Expand All @@ -56,32 +61,95 @@ func testAccGrafanaAuthKeyFromCloud(name, slug string) string {
`
}

// Checks that all API keys are deleted, to be called before the stack is completely destroyed
func testAccGrafanaAuthKeyCheckDestroyCloud(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "grafana_cloud_stack" {
continue
}

cloudClient := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI
c, cleanup, err := cloudClient.CreateTemporaryStackGrafanaClient(rs.Primary.Attributes["slug"], "test-api-key-", 60*time.Second)
func testAccGrafanaAuthCheckKeys(stack *gcom.FormattedApiInstance, expectedKeys []string) resource.TestCheckFunc {
return func(s *terraform.State) error {
cloudClient := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPIOpenAPI
c, cleanup, err := createTemporaryStackGrafanaClient(context.Background(), cloudClient, stack.Slug, "test-api-key-")
if err != nil {
return err
}
defer cleanup()

response, err := c.GetAPIKeys(true)
response, err := c.APIKeys.GetAPIkeys(api_keys.NewGetAPIkeysParams())
if err != nil {
return err
}

for _, key := range response {
var foundKeys []string
for _, key := range response.Payload {
if !strings.HasPrefix(key.Name, "test-api-key-") {
return fmt.Errorf("Found unexpected API key: %s", key.Name)
foundKeys = append(foundKeys, key.Name)
}
}

if len(foundKeys) != len(expectedKeys) {
return fmt.Errorf("expected %d keys, got %d", len(expectedKeys), len(foundKeys))
}
for _, expectedKey := range expectedKeys {
found := false
for _, foundKey := range foundKeys {
if expectedKey == foundKey {
found = true
break
}
}
if !found {
return fmt.Errorf("expected to find key %s, but it was not found", expectedKey)
}
}

return nil
}
}

func createTemporaryStackGrafanaClient(ctx context.Context, cloudClient *gcom.APIClient, stackSlug, tempSaPrefix string) (*goapi.GrafanaHTTPAPI, func() error, error) {
stack, _, err := cloudClient.InstancesAPI.GetInstance(ctx, stackSlug).Execute()
if err != nil {
return nil, nil, err
}

name := fmt.Sprintf("%s%d", tempSaPrefix, time.Now().UnixNano())

req := gcom.PostInstanceServiceAccountsRequest{
Name: name,
Role: "Admin",
}

sa, _, err := cloudClient.InstancesAPI.PostInstanceServiceAccounts(ctx, stackSlug).
PostInstanceServiceAccountsRequest(req).
XRequestId(cloud.ClientRequestID()).
Execute()
if err != nil {
return nil, nil, err
}

tokenRequest := gcom.PostInstanceServiceAccountTokensRequest{
Name: name,
SecondsToLive: common.Ref(int32(60)),
}
token, _, err := cloudClient.InstancesAPI.PostInstanceServiceAccountTokens(ctx, stackSlug, fmt.Sprintf("%d", sa.Id)).

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / unit tests

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 8.5.27 - oss - long

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / cloudinstance

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.2.0 - oss - long

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.1.5 - oss - long

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 9.5.13 - oss - long

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 8.5.27 - oss - basic

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.2.0 - enterprise - all

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.2.0 - oss - examples

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 8.5.27 - oss - other

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 9.5.13 - oss - basic

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.1.5 - oss - basic

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.2.0 - tls - basic

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.2.0 - oss - basic

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.2.0 - subpath - basic

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.2.0 - oss - other

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.2.0 - subpath - other

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 10.1.5 - oss - other

fmt.Sprintf format %d has arg sa.Id of wrong type float32

Check failure on line 130 in internal/resources/cloud/resource_cloud_stack_api_key_test.go

View workflow job for this annotation

GitHub Actions / 9.5.13 - oss - other

fmt.Sprintf format %d has arg sa.Id of wrong type float32
PostInstanceServiceAccountTokensRequest(tokenRequest).
XRequestId(cloud.ClientRequestID()).
Execute()
if err != nil {
return nil, nil, err
}

stackURLParsed, err := url.Parse(stack.Url)
if err != nil {
return nil, nil, err
}

client := goapi.NewHTTPClientWithConfig(nil, &goapi.TransportConfig{
Host: stackURLParsed.Host,
Schemes: []string{stackURLParsed.Scheme},
APIKey: token.Token,
})

cleanup := func() error {
_, err = client.ServiceAccounts.DeleteServiceAccount(int64(sa.Id))
return err
}

return errors.New("no cloud stack created")
return client, cleanup, nil
}
Loading

0 comments on commit 2dea0fe

Please sign in to comment.