diff --git a/go.mod b/go.mod index 14daaf077..da194a85d 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-openapi/strfmt v0.22.0 github.com/grafana/amixr-api-go-client v0.0.11 github.com/grafana/grafana-api-golang-client v0.27.0 - github.com/grafana/grafana-com-public-clients/go/gcom v0.0.0-20240126175209-247049a95c63 + github.com/grafana/grafana-com-public-clients/go/gcom v0.0.0-20240131153028-3f1ec24f35fa github.com/grafana/grafana-openapi-client-go v0.0.0-20240126032018-bd23c00af697 github.com/grafana/machine-learning-go-client v0.5.0 github.com/grafana/slo-openapi-client/go v0.0.0-20240112175006-de02e75b9d73 diff --git a/go.sum b/go.sum index 9ed23f2dc..f05f2a719 100644 --- a/go.sum +++ b/go.sum @@ -102,8 +102,8 @@ github.com/grafana/amixr-api-go-client v0.0.11 h1:jlE+5t0tRuCtjbpM81j70Dr2J4eCyS github.com/grafana/amixr-api-go-client v0.0.11/go.mod h1:N6x26XUrM5zGtK5zL5vNJnAn2JFMxLFPPLTw/6pDkFE= github.com/grafana/grafana-api-golang-client v0.27.0 h1:zIwMXcbCB4n588i3O2N6HfNcQogCNTd/vPkEXTr7zX8= github.com/grafana/grafana-api-golang-client v0.27.0/go.mod h1:uNLZEmgKtTjHBtCQMwNn3qsx2mpMb8zU+7T4Xv3NR9Y= -github.com/grafana/grafana-com-public-clients/go/gcom v0.0.0-20240126175209-247049a95c63 h1:Hvxkgh0MDYUlnyYOMai4kVbjRH6EuzctE1I5AFJRtOI= -github.com/grafana/grafana-com-public-clients/go/gcom v0.0.0-20240126175209-247049a95c63/go.mod h1:6sYY1qgwYfSDNQhKQA0tar8Oc38cIGfyqwejhxoOsPs= +github.com/grafana/grafana-com-public-clients/go/gcom v0.0.0-20240131153028-3f1ec24f35fa h1:mip69FpVOw1HM3GMA5DlwjSFmV22n1qrksgG/tt02BU= +github.com/grafana/grafana-com-public-clients/go/gcom v0.0.0-20240131153028-3f1ec24f35fa/go.mod h1:6sYY1qgwYfSDNQhKQA0tar8Oc38cIGfyqwejhxoOsPs= github.com/grafana/grafana-openapi-client-go v0.0.0-20240126032018-bd23c00af697 h1:8io6OuKJrhH8SEfwXV1ZpAwgaGhJ25/pjaA3vYmMxxE= github.com/grafana/grafana-openapi-client-go v0.0.0-20240126032018-bd23c00af697/go.mod h1:af7rlJw/VtbvAfI5VWzYO4p/pT58FXrN6XqZBnkwBxo= github.com/grafana/machine-learning-go-client v0.5.0 h1:Q1K+MPSy8vfMm2jsk3WQ7O77cGr2fM5hxwtPSoPc5NU= diff --git a/internal/resources/cloud/common.go b/internal/resources/cloud/common.go index 2ec8a9e85..e64e76d71 100644 --- a/internal/resources/cloud/common.go +++ b/internal/resources/cloud/common.go @@ -6,7 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" ) -func clientRequestID() string { +func ClientRequestID() string { uuid, err := uuid.GenerateUUID() if err != nil { return "" diff --git a/internal/resources/cloud/data_source_cloud_stack_test.go b/internal/resources/cloud/data_source_cloud_stack_test.go index e3f52f395..1a980e788 100644 --- a/internal/resources/cloud/data_source_cloud_stack_test.go +++ b/internal/resources/cloud/data_source_cloud_stack_test.go @@ -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" ) @@ -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) diff --git a/internal/resources/cloud/resource_cloud_api_key.go b/internal/resources/cloud/resource_cloud_api_key.go index fd67e0342..d7517fe08 100644 --- a/internal/resources/cloud/resource_cloud_api_key.go +++ b/internal/resources/cloud/resource_cloud_api_key.go @@ -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 apiError(err) @@ -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 apiError(err) } diff --git a/internal/resources/cloud/resource_cloud_api_key_test.go b/internal/resources/cloud/resource_cloud_api_key_test.go index 777efa300..891889b22 100644 --- a/internal/resources/cloud/resource_cloud_api_key_test.go +++ b/internal/resources/cloud/resource_cloud_api_key_test.go @@ -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" @@ -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), @@ -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) } diff --git a/internal/resources/cloud/resource_cloud_plugin.go b/internal/resources/cloud/resource_cloud_plugin.go index eb4cbabd3..5b871b1e6 100644 --- a/internal/resources/cloud/resource_cloud_plugin.go +++ b/internal/resources/cloud/resource_cloud_plugin.go @@ -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 apiError(err) } @@ -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 apiError(err) } diff --git a/internal/resources/cloud/resource_cloud_plugin_test.go b/internal/resources/cloud/resource_cloud_plugin_test.go index 332e06e70..a26e288f8 100644 --- a/internal/resources/cloud/resource_cloud_plugin_test.go +++ b/internal/resources/cloud/resource_cloud_plugin_test.go @@ -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" @@ -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" @@ -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) } diff --git a/internal/resources/cloud/resource_cloud_stack.go b/internal/resources/cloud/resource_cloud_stack.go index 1fd9f126a..6f506afd6 100644 --- a/internal/resources/cloud/resource_cloud_stack.go +++ b/internal/resources/cloud/resource_cloud_stack.go @@ -263,7 +263,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"): @@ -315,7 +315,7 @@ func UpdateStack(ctx context.Context, d *schema.ResourceData, meta interface{}) Description: common.Ref(d.Get("description").(string)), Url: common.Ref(d.Get("url").(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 apiError(err) @@ -331,7 +331,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 apiError(err) } diff --git a/internal/resources/cloud/resource_cloud_stack_api_key_test.go b/internal/resources/cloud/resource_cloud_stack_api_key_test.go index f4a3d5bf3..a43154248 100644 --- a/internal/resources/cloud/resource_cloud_stack_api_key_test.go +++ b/internal/resources/cloud/resource_cloud_stack_api_key_test.go @@ -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" @@ -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) @@ -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"), @@ -40,7 +45,7 @@ func TestAccGrafanaAuthKeyFromCloud(t *testing.T) { }, { Config: testAccStackConfigBasic(slug, slug, "description"), - Check: testAccGrafanaAuthKeyCheckDestroyCloud, + Check: testAccGrafanaAuthCheckKeys(&stack, []string{}), }, }, }) @@ -56,32 +61,98 @@ 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 + return fmt.Errorf("failed to get API keys: %w", 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", int(sa.Id))). + 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}, + BasePath: "api", + APIKey: token.Key, + NumRetries: 5, + RetryTimeout: 10 * time.Second, + }) + + cleanup := func() error { + _, err = client.ServiceAccounts.DeleteServiceAccount(int64(sa.Id)) + return err + } - return errors.New("no cloud stack created") + return client, cleanup, nil } diff --git a/internal/resources/cloud/resource_cloud_stack_service_account_test.go b/internal/resources/cloud/resource_cloud_stack_service_account_test.go index b2185924a..9b36bbf28 100644 --- a/internal/resources/cloud/resource_cloud_stack_service_account_test.go +++ b/internal/resources/cloud/resource_cloud_stack_service_account_test.go @@ -1,13 +1,13 @@ package cloud_test import ( - "errors" + "context" "fmt" "strings" "testing" - "time" - gapi "github.com/grafana/grafana-api-golang-client" + "github.com/grafana/grafana-com-public-clients/go/gcom" + "github.com/grafana/grafana-openapi-client-go/client/service_accounts" "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" @@ -17,7 +17,7 @@ import ( func TestAccGrafanaServiceAccountFromCloud(t *testing.T) { testutils.CheckCloudAPITestsEnabled(t) - var stack gapi.Stack + var stack gcom.FormattedApiInstance prefix := "tfsatest" slug := GetRandomStackName(prefix) @@ -32,6 +32,7 @@ func TestAccGrafanaServiceAccountFromCloud(t *testing.T) { Config: testAccGrafanaServiceAccountFromCloud(slug, slug), Check: resource.ComposeTestCheckFunc( testAccStackCheckExists("grafana_cloud_stack.test", &stack), + testAccGrafanaAuthCheckServiceAccounts(&stack, []string{"management-sa"}), resource.TestCheckResourceAttr("grafana_cloud_stack_service_account.management", "name", "management-sa"), resource.TestCheckResourceAttr("grafana_cloud_stack_service_account.management", "role", "Admin"), resource.TestCheckResourceAttr("grafana_cloud_stack_service_account.management", "is_disabled", "false"), @@ -42,7 +43,7 @@ func TestAccGrafanaServiceAccountFromCloud(t *testing.T) { }, { Config: testAccStackConfigBasic(slug, slug, "description"), - Check: testAccGrafanaServiceAccountCheckDestroyCloud, + Check: testAccGrafanaAuthCheckServiceAccounts(&stack, []string{}), }, }, }) @@ -64,43 +65,46 @@ func testAccGrafanaServiceAccountFromCloud(name, slug string) string { ` } -// Checks that all service accounts and service account tokens are deleted, to be called before the stack is completely destroyed -func testAccGrafanaServiceAccountCheckDestroyCloud(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-service-account-", 60*time.Second) +func testAccGrafanaAuthCheckServiceAccounts(stack *gcom.FormattedApiInstance, expectedSAs []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.GetServiceAccounts() + response, err := c.ServiceAccounts.SearchOrgServiceAccountsWithPaging(service_accounts.NewSearchOrgServiceAccountsWithPagingParams()) if err != nil { - return err + return fmt.Errorf("failed to get service accounts: %w", err) } - for _, sa := range response { - if strings.HasPrefix(sa.Name, "test-service-account-") { - continue // this is a service account created by this test + var foundSAs []string + for _, sa := range response.Payload.ServiceAccounts { + if !strings.HasPrefix(sa.Name, "test-api-key-") { + foundSAs = append(foundSAs, sa.Name) + if sa.Tokens == 0 { + return fmt.Errorf("expected to find at least one token for service account %s", sa.Name) + } } + } - tokens, err := c.GetServiceAccountTokens(sa.ID) - if err != nil { - return err + if len(foundSAs) != len(expectedSAs) { + return fmt.Errorf("expected %d keys, got %d", len(expectedSAs), len(foundSAs)) + } + for _, expectedSA := range expectedSAs { + found := false + for _, foundSA := range foundSAs { + if expectedSA == foundSA { + found = true + break + } } - if len(tokens) > 0 { - return fmt.Errorf("found unexpected service account tokens for service account %s: %v", sa.Name, tokens) + if !found { + return fmt.Errorf("expected to find key %s, but it was not found", expectedSA) } - - return fmt.Errorf("found unexpected service account: %v", sa) } return nil } - - return errors.New("no cloud stack created") } diff --git a/internal/resources/cloud/resource_cloud_stack_test.go b/internal/resources/cloud/resource_cloud_stack_test.go index cd2cc9877..e7565b9e9 100644 --- a/internal/resources/cloud/resource_cloud_stack_test.go +++ b/internal/resources/cloud/resource_cloud_stack_test.go @@ -1,16 +1,17 @@ package cloud_test import ( + "context" "fmt" "regexp" "strings" "time" - "strconv" "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/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" @@ -22,7 +23,7 @@ func TestResourceStack_Basic(t *testing.T) { prefix := "tfresourcetest" - var stack gapi.Stack + var stack gcom.FormattedApiInstance resourceName := GetRandomStackName(prefix) stackDescription := "This is a test stack" @@ -115,15 +116,15 @@ func TestResourceStack_Basic(t *testing.T) { } func testAccDeleteExistingStacks(t *testing.T, prefix string) { - client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI - resp, err := client.Stacks() + client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPIOpenAPI + resp, _, err := client.InstancesAPI.GetInstances(context.Background()).Execute() if err != nil { t.Error(err) } for _, stack := range resp.Items { if strings.HasPrefix(stack.Name, prefix) { - err := client.DeleteStack(stack.Slug) + _, _, err := client.InstancesAPI.DeleteInstance(context.Background(), stack.Slug).XRequestId(cloud.ClientRequestID()).Execute() if err != nil { t.Error(err) } @@ -131,7 +132,7 @@ func testAccDeleteExistingStacks(t *testing.T, prefix string) { } } -func testAccStackCheckExists(rn string, a *gapi.Stack) resource.TestCheckFunc { +func testAccStackCheckExists(rn string, a *gcom.FormattedApiInstance) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[rn] if !ok { @@ -141,29 +142,29 @@ func testAccStackCheckExists(rn string, a *gapi.Stack) resource.TestCheckFunc { if rs.Primary.ID == "" { return fmt.Errorf("resource id not set") } - id, err := strconv.ParseInt(rs.Primary.ID, 10, 64) - if err != nil { - return fmt.Errorf("resource id is malformed") - } - client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI - stack, err := client.StackByID(id) + client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPIOpenAPI + stack, _, err := client.InstancesAPI.GetInstance(context.Background(), rs.Primary.ID).Execute() if err != nil { return fmt.Errorf("error getting data source: %s", err) } - *a = stack + *a = *stack + + if destroyErr := testAccStackCheckDestroy(a)(s); destroyErr == nil { + return fmt.Errorf("expected the stack's destroy check to fail, but it didn't") + } return nil } } -func testAccStackCheckDestroy(a *gapi.Stack) resource.TestCheckFunc { +func testAccStackCheckDestroy(a *gcom.FormattedApiInstance) resource.TestCheckFunc { return func(s *terraform.State) error { - client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI - stack, err := client.StackBySlug(a.Slug) + client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPIOpenAPI + stack, _, err := client.InstancesAPI.GetInstance(context.Background(), a.Slug).Execute() if err == nil && stack.Name != "" { - return fmt.Errorf("stack `%s` with ID `%d` still exists after destroy", stack.Name, stack.ID) + return fmt.Errorf("stack `%s` with ID `%d` still exists after destroy", stack.Name, int(stack.Id)) } return nil diff --git a/internal/resources/cloud/resource_synthetic_monitoring_installation_test.go b/internal/resources/cloud/resource_synthetic_monitoring_installation_test.go index 92aac65c7..064cb19aa 100644 --- a/internal/resources/cloud/resource_synthetic_monitoring_installation_test.go +++ b/internal/resources/cloud/resource_synthetic_monitoring_installation_test.go @@ -3,7 +3,7 @@ package cloud_test import ( "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/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -17,7 +17,7 @@ func TestAccSyntheticMonitoringInstallation(t *testing.T) { "eu": "https://synthetic-monitoring-api-eu-west.grafana.net", } { t.Run(region, func(t *testing.T) { - var stack gapi.Stack + var stack gcom.FormattedApiInstance stackPrefix := "tfsminstalltest" testAccDeleteExistingStacks(t, stackPrefix) stackSlug := GetRandomStackName(stackPrefix)