Skip to content

Commit

Permalink
roles
Browse files Browse the repository at this point in the history
  • Loading branch information
phact committed Aug 12, 2021
1 parent aef8a8b commit 8843908
Show file tree
Hide file tree
Showing 4 changed files with 326 additions and 0 deletions.
107 changes: 107 additions & 0 deletions internal/provider/data_source_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package provider

import (
"context"
"fmt"
"github.com/datastax/astra-client-go/v2/astra"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceRole() *schema.Resource {
return &schema.Resource{
Description: "`astra_role` provides a datasource that lists the custom roles for an org.",

ReadContext: dataSourceAccessListRead,

Schema: map[string]*schema.Schema{
// Required
"role_id": {
Description: "Role ID, system generated",
Type: schema.TypeString,
Required: true,
},

// Computed
"results": {
Type: schema.TypeList,
Description: "The list of private links that match the search criteria.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"role_name": {
Description: "Role name",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Description: "Role description",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"effect": {
Description: "Role effect",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"resources": {
Description: "Resources for which role is applicable",
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},

"policy": {
Description: "List of policies for the role.",
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
},
}
}

func dataSourceRoleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
fmt.Printf("role data source")

client := meta.(*astra.ClientWithResponses)

roleID := d.Get("role_id").(string)

role, err := listRole(ctx, client, roleID)
if err != nil {
return diag.FromErr(err)
}

id := role["id"].(string)
d.SetId(id)
if err := d.Set("results", role); err != nil {
return diag.FromErr(err)
}


return nil
}

func listRole(ctx context.Context, client *astra.ClientWithResponses, roleID string) (map[string]interface{}, error) {
resp, err := client.GetOrganizationRoleWithResponse(ctx, astra.RoleIdParam(roleID))
if err != nil {
return nil, err
}

roleRaw := (*resp.JSON200).(map[string]interface{})

return roleRaw, err
}
2 changes: 2 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ func New(version string) func() *schema.Provider {
"astra_private_links": dataSourcePrivateLinks(),
"astra_private_link_endpoints": dataSourcePrivateLinkEndpoints(),
"astra_access_list": dataSourceAccessList(),
"astra_role": dataSourceRole(),
},
ResourcesMap: map[string]*schema.Resource{
"astra_database": resourceDatabase(),
"astra_keyspace": resourceKeyspace(),
"astra_private_link": resourcePrivateLink(),
"astra_private_link_endpoint": resourcePrivateLinkEndpoint(),
"astra_access_list": resourceAccessList(),
"astra_role": resourceRole(),
},
Schema: map[string]*schema.Schema{
"token": {
Expand Down
186 changes: 186 additions & 0 deletions internal/provider/resource_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package provider

import (
"context"
"errors"
"fmt"
"strings"

"github.com/datastax/astra-client-go/v2/astra"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceRole() *schema.Resource {
return &schema.Resource{
Description: "`astra_role` resource represents custom roles for a particular Astra Org. Custom roles can be assigned to an Astra user is to grant them granular permissions when the default roles in the UI are not specific enough. Roles are composed of policies which are granted to resources.",
CreateContext: resourceRoleCreate,
ReadContext: resourceRoleRead,
DeleteContext: resourceRoleDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
// Required
"role_name": {
Description: "Role name",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Description: "Role description",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"effect": {
Description: "Role effect",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"resources": {
Description: "Resources for which role is applicable",
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},

"policy": {
Description: "List of policies for the role.",
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"role_id": {
Description: "Role ID, system generated",
Type: schema.TypeString,
Computed: true,
ForceNew: true,
},
},
}
}

func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*astra.ClientWithResponses)

roleName := d.Get("role_name").(string)
description := d.Get("description").(string)
effect := d.Get("effect").(string)
resourcesRaw := d.Get("resources").([]interface{})
policyRaw := d.Get("policy")

actions := policyRaw.([]interface{})


resourcesList := make([]string, len(actions))
actionsList := make([]astra.PolicyActions, len(actions))

for k, v := range resourcesRaw {
resourcesList[k] = v.(string)
}
for k, v := range policyRaw.([]interface{}) {
actionsList[k] = astra.PolicyActions(v.(string))
}
policy := astra.Policy{
Actions: actionsList,
Description: description,
Effect: astra.PolicyEffect(effect),
Resources: resourcesList,
}


roleJSON := astra.AddOrganizationRoleJSONRequestBody{
Name: roleName,
Policy: policy,
}
resp, err := client.AddOrganizationRoleWithResponse(ctx,
roleJSON,
)

if err != nil {
return diag.FromErr(err)
} else if resp.StatusCode() >= 400 {
return diag.Errorf("error adding role to org: %s", resp.Body)
}

role := resp.JSON201
if err := setRoleData(d, *role.Id); err != nil {
return diag.FromErr(err)
}

return nil
}

func resourceRoleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*astra.ClientWithResponses)

id := d.Id()

roleID, err := parseRoleID(id)
if err != nil {
return diag.FromErr(err)
}

roleParam := astra.RoleIdParam(roleID)
client.DeleteOrganizationRoleWithResponse(ctx, roleParam)

return nil
}

func resourceRoleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*astra.ClientWithResponses)

id := d.Id()

roleID, err := parseRoleID(id)
if err != nil {
return diag.FromErr(err)
}

role, err := listRole(ctx, client, roleID)
if err != nil {
return diag.FromErr(err)
}


if role["id"].(string) == roleID {
if err := setRoleData(d, roleID); err != nil {
return diag.FromErr(err)
}
return nil
}

// Not found. Remove from state.
d.SetId("")

return nil
}

func setRoleData(d *schema.ResourceData, roleID string) error {
d.SetId(fmt.Sprintf("%s", roleID))

if err := d.Set("role_id", roleID); err != nil {
return err
}

return nil
}

func parseRoleID(id string) (string, error) {
idParts := strings.Split(strings.ToLower(id), "/")
if len(idParts) != 1 {
return "", errors.New("invalid role id format: expected roleID/")
}
return idParts[0], nil
}
31 changes: 31 additions & 0 deletions internal/provider/resource_role_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package provider

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"testing"
)

func TestRole(t *testing.T){
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccRoleConfiguration(),
},
},
})
}

func testAccRoleConfiguration() string {
return fmt.Sprintf(`
resource "astra_role" "example" {
role_name = "puppies"
description = "test role"
effect = "allow"
resources = ["drn:astra:org:f9f4b1e0-4c05-451e-9bba-d631295a7f73"]
policy = ["db-all-keyspace-create"]
}
`)
}

0 comments on commit 8843908

Please sign in to comment.