Skip to content

Commit

Permalink
Add org support for role None (#1068)
Browse files Browse the repository at this point in the history
* Add org support for role None

* Regenerating docs

* Update docs/resources/organization.md

Co-authored-by: Eric Leijonmarck <[email protected]>

* Update internal/resources/grafana/resource_organization.go

Co-authored-by: Eric Leijonmarck <[email protected]>

* Regenerating docs

* Testing assignment and removal of role none

* making ad-hoc test

* Rename list from nones to users_without_access

* Regen docs and map roles to role lists

* More generic functions to obtain role name and role list name

* Update docs/resources/organization.md

Co-authored-by: Ieva <[email protected]>

* Update internal/resources/grafana/resource_organization.go

Co-authored-by: Ieva <[email protected]>

* Fix semver check + add 10.2 notice

---------

Co-authored-by: Eric Leijonmarck <[email protected]>
Co-authored-by: Ieva <[email protected]>
Co-authored-by: Julien Duchesne <[email protected]>
  • Loading branch information
4 people authored Nov 1, 2023
1 parent 607305c commit 5f99abc
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 7 deletions.
5 changes: 4 additions & 1 deletion docs/resources/organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ description: |-
* [HTTP API](https://grafana.com/docs/grafana/latest/developers/http_api/org/)

This resource represents an instance-scoped resource and uses Grafana's admin APIs.
It does not work with API tokens or service accounts which are org-scoped.
It does not work with API tokens or service accounts which are org-scoped.
You must use basic auth.

## Example Usage
Expand Down Expand Up @@ -67,6 +67,9 @@ already exist in Grafana.
- `editors` (Set of String) A list of email addresses corresponding to users who should be given editor
access to the organization. Note: users specified here must already exist in
Grafana unless 'create_users' is set to true.
- `users_without_access` (Set of String) A list of email addresses corresponding to users who should be given none access to the organization.
Note: users specified here must already exist in Grafana, unless 'create_users' is
set to true. This feature is only available in Grafana 10.2+.
- `viewers` (Set of String) A list of email addresses corresponding to users who should be given viewer
access to the organization. Note: users specified here must already exist in
Grafana unless 'create_users' is set to true.
Expand Down
41 changes: 35 additions & 6 deletions internal/resources/grafana/resource_organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func ResourceOrganization() *schema.Resource {
* [HTTP API](https://grafana.com/docs/grafana/latest/developers/http_api/org/)
This resource represents an instance-scoped resource and uses Grafana's admin APIs.
It does not work with API tokens or service accounts which are org-scoped.
It does not work with API tokens or service accounts which are org-scoped.
You must use basic auth.
`,

Expand Down Expand Up @@ -125,6 +125,18 @@ Grafana unless 'create_users' is set to true.
A list of email addresses corresponding to users who should be given viewer
access to the organization. Note: users specified here must already exist in
Grafana unless 'create_users' is set to true.
`,
},
"users_without_access": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: `
A list of email addresses corresponding to users who should be given none access to the organization.
Note: users specified here must already exist in Grafana, unless 'create_users' is
set to true. This feature is only available in Grafana 10.2+.
`,
},
},
Expand Down Expand Up @@ -198,15 +210,15 @@ func ReadUsers(d *schema.ResourceData, meta interface{}) error {
if err != nil {
return err
}
roleMap := map[string][]string{"Admin": nil, "Editor": nil, "Viewer": nil}
roleMap := map[string][]string{"Admin": nil, "Editor": nil, "Viewer": nil, "None": nil}
grafAdmin := d.Get("admin_user")
for _, orgUser := range orgUsers {
if orgUser.Login != grafAdmin {
roleMap[orgUser.Role] = append(roleMap[orgUser.Role], orgUser.Email)
}
}
for k, v := range roleMap {
d.Set(fmt.Sprintf("%ss", strings.ToLower(k)), v)
d.Set(getRoleListName(k), v)
}
return nil
}
Expand All @@ -226,11 +238,10 @@ func UpdateUsers(d *schema.ResourceData, meta interface{}) error {
}

func collectUsers(d *schema.ResourceData) (map[string]OrgUser, map[string]OrgUser, error) {
roles := []string{"admins", "editors", "viewers"}
roles := []string{"admins", "editors", "viewers", "users_without_access"}
stateUsers, configUsers := make(map[string]OrgUser), make(map[string]OrgUser)
for _, role := range roles {
caser := cases.Title(language.English)
roleName := caser.String(role[:len(role)-1])
roleName := getRoleName(role)
// Get the lists of users read in from Grafana state (old) and configured (new)
state, config := d.GetChange(role)
for _, u := range state.(*schema.Set).List() {
Expand Down Expand Up @@ -352,3 +363,21 @@ func applyChanges(meta interface{}, orgID int64, changes []UserChange) error {
}
return nil
}

func getRoleName(listName string) string {
if listName == "users_without_access" {
return "None"
}

caser := cases.Title(language.English)
roleName := caser.String(listName[:len(listName)-1])
return roleName
}

func getRoleListName(roleName string) string {
if roleName == "None" {
return "users_without_access"
}

return fmt.Sprintf("%ss", strings.ToLower(roleName))
}
76 changes: 76 additions & 0 deletions internal/resources/grafana/resource_organization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ func TestAccOrganization_users(t *testing.T) {
resource.TestCheckNoResourceAttr(
"grafana_organization.test", "viewers.#",
),
resource.TestCheckNoResourceAttr(
"grafana_organization.test", "users_without_access.#",
),
),
},
{
Expand All @@ -110,6 +113,9 @@ func TestAccOrganization_users(t *testing.T) {
resource.TestCheckNoResourceAttr(
"grafana_organization.test", "viewers.#",
),
resource.TestCheckNoResourceAttr(
"grafana_organization.test", "users_without_access.#",
),
),
},
{
Expand All @@ -128,6 +134,64 @@ func TestAccOrganization_users(t *testing.T) {
resource.TestCheckResourceAttr(
"grafana_organization.test", "viewers.#", "0",
),
resource.TestCheckResourceAttr(
"grafana_organization.test", "users_without_access.#", "0",
),
),
},
},
})
}

func TestAccOrganization_roleNoneUser(t *testing.T) {
testutils.CheckOSSTestsEnabled(t, ">=10.2.0")

var org gapi.Org

resource.Test(t, resource.TestCase{
ProviderFactories: testutils.ProviderFactories,
CheckDestroy: testAccOrganizationCheckDestroy(&org),
Steps: []resource.TestStep{
{
Config: testAccOrganizationConfig_usersCreate,
Check: resource.ComposeTestCheckFunc(
testAccOrganizationCheckExists("grafana_organization.test", &org),
resource.TestCheckResourceAttr(
"grafana_organization.test", "admins.#", "1",
),
),
},
{
Config: testAccOrganization_roleNoneUsersUpdate,
Check: resource.ComposeTestCheckFunc(
testAccOrganizationCheckExists("grafana_organization.test", &org),
resource.TestCheckResourceAttr(
"grafana_organization.test", "name", "terraform-acc-test",
),
resource.TestCheckNoResourceAttr(
"grafana_organization.test", "admins.#",
),
resource.TestCheckNoResourceAttr(
"grafana_organization.test", "editors.#",
),
resource.TestCheckNoResourceAttr(
"grafana_organization.test", "viewers.#",
),
resource.TestCheckResourceAttr(
"grafana_organization.test", "users_without_access.#", "1",
),
),
},
{
Config: testAccOrganizationConfig_usersRemove,
Check: resource.ComposeTestCheckFunc(
testAccOrganizationCheckExists("grafana_organization.test", &org),
resource.TestCheckResourceAttr(
"grafana_organization.test", "admins.#", "0",
),
resource.TestCheckResourceAttr(
"grafana_organization.test", "users_without_access.#", "0",
),
),
},
},
Expand Down Expand Up @@ -329,6 +393,18 @@ resource "grafana_organization" "test" {
]
}
`
const testAccOrganization_roleNoneUsersUpdate = `
resource "grafana_organization" "test" {
name = "terraform-acc-test"
admin_user = "admin"
create_users = false
editors = []
users_without_access = [
"[email protected]",
]
}
`

const testAccOrganizationConfig_usersRemove = `
resource "grafana_organization" "test" {
name = "terraform-acc-test"
Expand Down

0 comments on commit 5f99abc

Please sign in to comment.