Skip to content

Commit

Permalink
Folder/Dashboard Permissions Tests: Use OpenAPI
Browse files Browse the repository at this point in the history
Also:
- Make the tests for these two resource roughly the same. These resources have the same interface
- Actually test that permissions are applied in Grafana. The current checks were only fetching without checking. But you can fetch permissions on a folder/dashboard without any permissions
- For dashboard, check that either setting empty permissions or deleting the resource actually removes the permissions
  • Loading branch information
julienduchesne committed Dec 15, 2023
1 parent 3db0477 commit cd9fe4b
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 253 deletions.
298 changes: 144 additions & 154 deletions internal/resources/grafana/resource_dashboard_permission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,74 @@ package grafana_test

import (
"fmt"
"strconv"
"testing"

"github.com/grafana/terraform-provider-grafana/internal/common"
"github.com/grafana/grafana-openapi-client-go/models"
"github.com/grafana/terraform-provider-grafana/internal/resources/grafana"
"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"
)

func TestAccDashboardPermission_basic(t *testing.T) {
testutils.CheckOSSTestsEnabled(t, ">=9.0.0") // Dashboard UIDs are only available as references in Grafana 9+
testutils.CheckOSSTestsEnabled(t, ">=9.0.0")

dashboardUID := ""
var (
dashboard models.DashboardFullWithMeta
team models.TeamDTO
user models.UserProfileDTO
sa models.ServiceAccountDTO
)

// TODO: Make parallelizable
resource.Test(t, resource.TestCase{
ProviderFactories: testutils.ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccDashboardPermissionConfig_Basic,
Config: testAccDashboardPermissionConfig(true, true),
Check: resource.ComposeAggregateTestCheckFunc(
testAccDashboardPermissionsCheckExistsUID("grafana_dashboard_permission.testPermission", &dashboardUID),
dashboardCheckExists.exists("grafana_dashboard.testDashboard", &dashboard),
teamCheckExists.exists("grafana_team.testTeam", &team),
userCheckExists.exists("grafana_user.testAdminUser", &user),
serviceAccountCheckExists.exists("grafana_service_account.test", &sa),

resource.TestCheckResourceAttr("grafana_dashboard_permission.testPermission", "permissions.#", "5"),
checkDashboardPermissionsSet(&dashboard, &team, &user, &sa),
),
},
{
ImportState: true,
ResourceName: "grafana_dashboard_permission.testPermission",
ImportStateVerify: true,
},
// Test remove permissions by not setting any permissions
{
Config: testAccDashboardPermissionConfig(true, false),
Check: resource.ComposeAggregateTestCheckFunc(
dashboardCheckExists.exists("grafana_dashboard.testDashboard", &dashboard),
resource.TestCheckResourceAttr("grafana_dashboard_permission.testPermission", "permissions.#", "0"),
checkDashboardPermissionsEmpty(&dashboard),
),
},
// Reapply permissions
{
Config: testAccDashboardPermissionConfig(true, true),
Check: resource.ComposeAggregateTestCheckFunc(
dashboardCheckExists.exists("grafana_dashboard.testDashboard", &dashboard),
teamCheckExists.exists("grafana_team.testTeam", &team),
userCheckExists.exists("grafana_user.testAdminUser", &user),
serviceAccountCheckExists.exists("grafana_service_account.test", &sa),

resource.TestCheckResourceAttr("grafana_dashboard_permission.testPermission", "permissions.#", "5"),
checkDashboardPermissionsSet(&dashboard, &team, &user, &sa),
),
},
// Test remove permissions by removing the resource
{
Config: testAccDashboardPermissionConfig_Remove,
Config: testutils.WithoutResource(t, testAccDashboardPermissionConfig(true, true), "grafana_dashboard_permission.testPermission"),
Check: resource.ComposeAggregateTestCheckFunc(
testAccDashboardPermissionsCheckEmptyUID(&dashboardUID),
dashboardCheckExists.exists("grafana_dashboard.testDashboard", &dashboard),
checkDashboardPermissionsEmpty(&dashboard),
),
},
},
Expand All @@ -46,96 +79,138 @@ func TestAccDashboardPermission_basic(t *testing.T) {
// Testing the deprecated case of using a dashboard ID instead of a dashboard UID
// TODO: Remove in next major version
func TestAccDashboardPermission_fromDashboardID(t *testing.T) {
testutils.CheckOSSTestsEnabled(t)
testutils.CheckOSSTestsEnabled(t, ">=9.0.0")

dashboardID := int64(-1)
var (
dashboard models.DashboardFullWithMeta
team models.TeamDTO
user models.UserProfileDTO
sa models.ServiceAccountDTO
)

// TODO: Make parallelizable
resource.Test(t, resource.TestCase{
ProviderFactories: testutils.ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccDashboardPermissionConfig_FromID,
Config: testAccDashboardPermissionConfig(false, true),
Check: resource.ComposeAggregateTestCheckFunc(
testAccDashboardPermissionsCheckExists("grafana_dashboard_permission.testPermission", &dashboardID),
resource.TestCheckResourceAttr("grafana_dashboard_permission.testPermission", "permissions.#", "4"),
dashboardCheckExists.exists("grafana_dashboard.testDashboard", &dashboard),
teamCheckExists.exists("grafana_team.testTeam", &team),
userCheckExists.exists("grafana_user.testAdminUser", &user),
serviceAccountCheckExists.exists("grafana_service_account.test", &sa),

resource.TestCheckResourceAttr("grafana_dashboard_permission.testPermission", "permissions.#", "5"),
checkDashboardPermissionsSet(&dashboard, &team, &user, &sa),
),
},
{
ImportState: true,
ResourceName: "grafana_dashboard_permission.testPermission",
ImportStateVerify: true,
},
},
})
}

func testAccDashboardPermissionsCheckExistsUID(rn string, dashboardUID *string) resource.TestCheckFunc {
func checkDashboardPermissionsSet(dashboard *models.DashboardFullWithMeta, team *models.TeamDTO, user *models.UserProfileDTO, sa *models.ServiceAccountDTO) 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")
}

orgID, gotDashboardUID := grafana.SplitOrgResourceID(rs.Primary.ID)
client := testutils.Provider.Meta().(*common.Client).DeprecatedGrafanaAPI.WithOrgID(orgID)

_, err := client.DashboardPermissionsByUID(gotDashboardUID)
if err != nil {
return fmt.Errorf("Error getting dashboard permissions: %s", err)
expectedPerms := []*models.DashboardACLInfoDTO{
{
Role: "Viewer",
PermissionName: "View",
},
{
Role: "Editor",
PermissionName: "Edit",
},
{
TeamID: team.ID,
PermissionName: "View",
},
{
UserID: user.ID,
PermissionName: "Admin",
},
{
UserID: sa.ID,
PermissionName: "Admin",
},
}

*dashboardUID = gotDashboardUID

return nil
return checkDashboardPermissions(dashboard, expectedPerms)
}
}

func testAccDashboardPermissionsCheckExists(rn string, dashboardID *int64) resource.TestCheckFunc {
func checkDashboardPermissionsEmpty(dashboard *models.DashboardFullWithMeta) 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)
}
return checkDashboardPermissions(dashboard, []*models.DashboardACLInfoDTO{})
}
}

if rs.Primary.ID == "" {
return fmt.Errorf("Resource id not set")
}
func checkDashboardPermissions(dashboard *models.DashboardFullWithMeta, expectedPerms []*models.DashboardACLInfoDTO) error {
client := grafana.OAPIGlobalClient(testutils.Provider.Meta())
uid := dashboard.Dashboard.(map[string]interface{})["uid"].(string)
resp, err := client.DashboardPermissions.GetDashboardPermissionsListByUID(uid)
if err != nil {
return fmt.Errorf("error getting dashboard permissions: %s", err)
}
gotPerms := resp.Payload

orgID, dashboardIDStr := grafana.SplitOrgResourceID(rs.Primary.ID)
client := testutils.Provider.Meta().(*common.Client).DeprecatedGrafanaAPI.WithOrgID(orgID)
if len(gotPerms) != len(expectedPerms) {
return fmt.Errorf("got %d perms, expected %d", len(gotPerms), len(expectedPerms))
}

gotDashboardID, err := strconv.ParseInt(dashboardIDStr, 10, 64)
if err != nil {
return fmt.Errorf("dashboard id is malformed")
for _, expectedPerm := range expectedPerms {
found := false
for _, gotPerm := range gotPerms {
if gotPerm.PermissionName == expectedPerm.PermissionName &&
gotPerm.Role == expectedPerm.Role &&
gotPerm.UserID == expectedPerm.UserID &&
gotPerm.TeamID == expectedPerm.TeamID {
found = true
break
}
}

_, err = client.DashboardPermissions(gotDashboardID)
if err != nil {
return fmt.Errorf("Error getting dashboard permissions: %s", err)
if !found {
return fmt.Errorf("didn't find permission matching %+v", expectedPerm)
}

*dashboardID = gotDashboardID

return nil
}

return nil
}

func testAccDashboardPermissionsCheckEmptyUID(dashboardUID *string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := testutils.Provider.Meta().(*common.Client).DeprecatedGrafanaAPI
permissions, err := client.DashboardPermissionsByUID(*dashboardUID)
if err != nil {
return fmt.Errorf("Error getting dashboard permissions %s: %s", *dashboardUID, err)
}
if len(permissions) > 0 {
return fmt.Errorf("Permissions were not empty when expected")
}
func testAccDashboardPermissionConfig(refDashboardByUID bool, hasPermissions bool) string {
ref := "dashboard_id = grafana_dashboard.testDashboard.dashboard_id"
if refDashboardByUID {
ref = "dashboard_uid = grafana_dashboard.testDashboard.uid"
}

return nil
perms := ""
if hasPermissions {
perms = `permissions {
role = "Viewer"
permission = "View"
}
permissions {
role = "Editor"
permission = "Edit"
}
permissions {
team_id = grafana_team.testTeam.id
permission = "View"
}
permissions {
user_id = grafana_user.testAdminUser.id
permission = "Admin"
}
permissions {
user_id = grafana_service_account.test.id
permission = "Admin"
}`
}
}

const testAccDashboardPermissionConfig_Basic = `
return fmt.Sprintf(`
resource "grafana_dashboard" "testDashboard" {
config_json = <<EOT
{
Expand Down Expand Up @@ -164,93 +239,8 @@ resource "grafana_service_account" "test" {
}
resource "grafana_dashboard_permission" "testPermission" {
dashboard_uid = grafana_dashboard.testDashboard.uid
permissions {
role = "Viewer"
permission = "View"
}
permissions {
role = "Editor"
permission = "Edit"
}
permissions {
team_id = grafana_team.testTeam.id
permission = "View"
}
permissions {
user_id = grafana_user.testAdminUser.id
permission = "Admin"
}
permissions {
user_id = grafana_service_account.test.id
permission = "Admin"
}
}
`
const testAccDashboardPermissionConfig_Remove = `
resource "grafana_dashboard" "testDashboard" {
config_json = <<EOT
{
"title": "Terraform Dashboard Permission Test Dashboard",
"id": 14,
"version": "43",
"uid": "someuid"
}
EOT
}
resource "grafana_team" "testTeam" {
name = "terraform-test-team-dashboard-permissions"
}
resource "grafana_user" "testAdminUser" {
email = "terraform-test-dashboard-permissions@localhost"
name = "Terraform Test Dashboard Permissions"
login = "ttdp"
password = "zyx987"
}
`

const testAccDashboardPermissionConfig_FromID = `
resource "grafana_dashboard" "testDashboard" {
config_json = <<EOT
{
"title": "Terraform Dashboard Permission Test Dashboard",
"id": 14,
"version": "43",
"uid": "someuid"
}
EOT
%s
%s
}
resource "grafana_team" "testTeam" {
name = "terraform-test-team-permissions"
}
resource "grafana_user" "testAdminUser" {
email = "terraform-test-dashboard-permissions@localhost"
name = "Terraform Test Dashboard Permissions"
login = "ttdp"
password = "zyx987"
}
resource "grafana_dashboard_permission" "testPermission" {
dashboard_id = grafana_dashboard.testDashboard.dashboard_id
permissions {
role = "Viewer"
permission = "View"
}
permissions {
role = "Editor"
permission = "Edit"
}
permissions {
team_id = grafana_team.testTeam.id
permission = "View"
}
permissions {
user_id = grafana_user.testAdminUser.id
permission = "Admin"
}
`, ref, perms)
}
`
Loading

0 comments on commit cd9fe4b

Please sign in to comment.