Skip to content

Commit

Permalink
Cloud Plugin: Use OpenAPI client (#1311)
Browse files Browse the repository at this point in the history
* Cloud Plugin: Use OpenAPI client

* Use random stack for plugin test

* Fix tests
- Allow empty region on stack
- Actually test cloud plugin deletion
- Destroy == opposite of Exists in a test
  • Loading branch information
julienduchesne authored Jan 29, 2024
1 parent 1561c84 commit acee375
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 53 deletions.
21 changes: 13 additions & 8 deletions internal/resources/cloud/resource_cloud_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"strings"

"github.com/grafana/grafana-com-public-clients/go/gcom"
"github.com/grafana/terraform-provider-grafana/internal/common"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -47,13 +48,18 @@ Manages Grafana Cloud Plugin Installations.
}

func ResourcePluginInstallationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI
client := meta.(*common.Client).GrafanaCloudAPIOpenAPI

stackSlug := d.Get("stack_slug").(string)
pluginSlug := d.Get("slug").(string)
pluginVersion := d.Get("version").(string)

_, err := client.InstallCloudPlugin(stackSlug, pluginSlug, pluginVersion)
req := gcom.PostInstancePluginsRequest{
Plugin: pluginSlug,
Version: common.Ref(d.Get("version").(string)),
}
_, _, err := client.InstancesAPI.PostInstancePlugins(ctx, stackSlug).
PostInstancePluginsRequest(req).
XRequestId(clientRequestID()).Execute()
if err != nil {
return diag.FromErr(err)
}
Expand All @@ -64,12 +70,12 @@ func ResourcePluginInstallationCreate(ctx context.Context, d *schema.ResourceDat
}

func ResourcePluginInstallationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI
client := meta.(*common.Client).GrafanaCloudAPIOpenAPI

splitID := strings.SplitN(d.Id(), "_", 2)
stackSlug, pluginSlug := splitID[0], splitID[1]

installation, err := client.GetCloudPluginInstallation(stackSlug, pluginSlug)
installation, _, err := client.InstancesAPI.GetInstancePlugin(ctx, stackSlug, pluginSlug).Execute()
if err, shouldReturn := common.CheckReadError("plugin", d, err); shouldReturn {
return err
}
Expand All @@ -82,12 +88,11 @@ func ResourcePluginInstallationRead(ctx context.Context, d *schema.ResourceData,
}

func ResourcePluginInstallationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*common.Client).GrafanaCloudAPI
client := meta.(*common.Client).GrafanaCloudAPIOpenAPI

splitID := strings.SplitN(d.Id(), "_", 2)
stackSlug, pluginSlug := splitID[0], splitID[1]

err := client.UninstallCloudPlugin(stackSlug, pluginSlug)

_, _, err := client.InstancesAPI.DeleteInstancePlugin(ctx, stackSlug, pluginSlug).XRequestId(clientRequestID()).Execute()
return diag.FromErr(err)
}
72 changes: 31 additions & 41 deletions internal/resources/cloud/resource_cloud_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package cloud_test

import (
"fmt"
"os"
"testing"

gapi "github.com/grafana/grafana-api-golang-client"
"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,21 +14,23 @@ import (
func TestAccResourcePluginInstallation(t *testing.T) {
testutils.CheckCloudAPITestsEnabled(t)

slug := os.Getenv("GRAFANA_CLOUD_ORG")
var stack gapi.Stack
stackPrefix := "tfplugin"
stackSlug := GetRandomStackName(stackPrefix)
pluginSlug := "aws-datasource-provisioner-app"
pluginVersion := "1.7.0"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccCloudPluginDeleteExisting(t, slug, pluginSlug) },

PreCheck: func() { testAccDeleteExistingStacks(t, stackPrefix) },
ProviderFactories: testutils.ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccGrafanaCloudPluginInstallation(slug, pluginSlug, pluginVersion),
Config: testAccGrafanaCloudPluginInstallation(stackSlug, pluginSlug, pluginVersion),
Check: resource.ComposeTestCheckFunc(
testAccCloudPluginInstallationCheckExists("grafana_cloud_plugin_installation.test-installation", slug, pluginSlug),
testAccStackCheckExists("grafana_cloud_stack.test", &stack),
testAccCloudPluginInstallationCheckExists(stackSlug, pluginSlug),
resource.TestCheckResourceAttrSet("grafana_cloud_plugin_installation.test-installation", "id"),
resource.TestCheckResourceAttr("grafana_cloud_plugin_installation.test-installation", "stack_slug", slug),
resource.TestCheckResourceAttr("grafana_cloud_plugin_installation.test-installation", "stack_slug", stackSlug),
resource.TestCheckResourceAttr("grafana_cloud_plugin_installation.test-installation", "slug", "aws-datasource-provisioner-app"),
resource.TestCheckResourceAttr("grafana_cloud_plugin_installation.test-installation", "version", "1.7.0")),
},
Expand All @@ -37,22 +39,21 @@ func TestAccResourcePluginInstallation(t *testing.T) {
ImportState: true,
ImportStateVerify: true,
},
// Test deletion (stack must keep existing to really test deletion)
{
Config: testutils.WithoutResource(t, testAccGrafanaCloudPluginInstallation(stackSlug, pluginSlug, pluginVersion), "grafana_cloud_plugin_installation.test-installation"),
Check: resource.ComposeTestCheckFunc(
testAccStackCheckExists("grafana_cloud_stack.test", &stack),
testAccCloudPluginInstallationDestroy(stackSlug, pluginSlug),
),
},
},
CheckDestroy: testAccCloudPluginInstallationDestroy(pluginSlug, pluginVersion),
CheckDestroy: testAccStackCheckDestroy(&stack),
})
}

func testAccCloudPluginInstallationCheckExists(rn string, stackSlug string, pluginSlug string) resource.TestCheckFunc {
func testAccCloudPluginInstallationCheckExists(stackSlug string, pluginSlug string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[rn]
if !ok {
return fmt.Errorf("resource not found: %s\n %#v", rn, s.RootModule().Resources)
}

if rs.Primary.ID == "" {
return fmt.Errorf("resource id not set")
}

client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI
_, err := client.GetCloudPluginInstallation(stackSlug, pluginSlug)
if err != nil {
Expand All @@ -65,37 +66,26 @@ func testAccCloudPluginInstallationCheckExists(rn string, stackSlug string, plug

func testAccCloudPluginInstallationDestroy(stackSlug string, pluginSlug string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI

installation, err := client.GetCloudPluginInstallation(stackSlug, pluginSlug)
if err == nil {
return fmt.Errorf("installation `%s` with ID `%d` still exists after destroy", installation.PluginSlug, installation.ID)
existsErr := testAccCloudPluginInstallationCheckExists(stackSlug, pluginSlug)(s)
if existsErr == nil {
return fmt.Errorf("installation still exists")
}

return nil
}
}

func testAccCloudPluginDeleteExisting(t *testing.T, instanceSlug, pluginSlug string) {
client := testutils.Provider.Meta().(*common.Client).GrafanaCloudAPI
installed, err := client.IsCloudPluginInstalled(instanceSlug, pluginSlug)
if err != nil {
t.Fatalf("error checking if plugin is installed: %s", err)
}
if installed {
err = client.UninstallCloudPlugin(instanceSlug, pluginSlug)
if err != nil {
t.Fatalf("error uninstalling plugin: %s", err)
}
}
}

func testAccGrafanaCloudPluginInstallation(stackSlug, name, version string) string {
return fmt.Sprintf(`
resource "grafana_cloud_stack" "test" {
name = "%[1]s"
slug = "%[1]s"
wait_for_readiness = false
}
resource "grafana_cloud_plugin_installation" "test-installation" {
stack_slug = "%s"
slug = "%s"
version = "%s"
stack_slug = grafana_cloud_stack.test.slug
slug = "%[2]s"
version = "%[3]s"
}
`, stackSlug, name, version)
}
13 changes: 9 additions & 4 deletions internal/resources/cloud/resource_cloud_stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,19 @@ func ResourceStack() *schema.Resource {
Description: `
Subdomain that the Grafana instance will be available at (i.e. setting slug to “<stack_slug>” will make the instance
available at “https://<stack_slug>.grafana.net".`,
ValidateFunc: validation.StringMatch(stackSlugRegex, "must be a lowercase alphanumeric string and must start with a letter."),
ValidateFunc: validation.All(
validation.StringMatch(stackSlugRegex, "must be a lowercase alphanumeric string and must start with a letter."),
validation.StringLenBetween(1, 29),
),
},
"region_slug": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `Region slug to assign to this stack. Changing region will destroy the existing stack and create a new one in the desired region. Use the region list API to get the list of available regions: https://grafana.com/docs/grafana-cloud/developer-resources/api-reference/cloud-api/#list-regions.`,
DiffSuppressFunc: func(_, oldValue, newValue string, _ *schema.ResourceData) bool {
return oldValue == newValue || newValue == "" // Ignore default region
},
},
"url": {
Type: schema.TypeString,
Expand All @@ -81,9 +87,8 @@ available at “https://<stack_slug>.grafana.net".`,
Optional: true,
Default: true,
Description: "Whether to wait for readiness of the stack after creating it. The check is a HEAD request to the stack URL (Grafana instance).",
// Suppress the diff if the new value is "false" because this attribute is only used at creation-time
// If the diff is suppress for a "true" value, the attribute cannot be read at all
DiffSuppressFunc: func(_, _, newValue string, _ *schema.ResourceData) bool { return newValue == "false" },
// Suppress the diff if the stack is already created
DiffSuppressFunc: func(_, _, _ string, d *schema.ResourceData) bool { return !d.IsNewResource() },
},
"wait_for_readiness_timeout": {
Type: schema.TypeString,
Expand Down

0 comments on commit acee375

Please sign in to comment.