Skip to content

Commit

Permalink
PLT-1483: Added role management suppport in terraform. (#540)
Browse files Browse the repository at this point in the history
  • Loading branch information
SivaanandM authored Nov 13, 2024
1 parent 1cee37c commit ef57d9c
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 3 deletions.
60 changes: 60 additions & 0 deletions docs/resources/role.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
page_title: "spectrocloud_role Resource - terraform-provider-spectrocloud"
subcategory: ""
description: |-
The role resource allows you to manage roles in Palette.
---

# spectrocloud_role (Resource)

The role resource allows you to manage roles in Palette.

You can learn more about managing roles in Palette by reviewing the [Roles](https://docs.spectrocloud.com/glossary-all/#role) guide.

## Example Usage

```terraform
variable "roles" {
type = list(string)
default = ["Cluster Admin", "Cluster Profile Editor"]
}
# Data source loop to retrieve multiple roles
data "spectrocloud_role" "roles" {
for_each = toset(var.roles)
name = each.key
}
resource "spectrocloud_role" "custom_role" {
name = "Test Cluster Role"
type = "project"
permissions = flatten([for role in data.spectrocloud_role.roles : role.permissions])
}
```


<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) The name of the role.
- `permissions` (Set of String) The permission's assigned to the role.

### Optional

- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- `type` (String) The role type. Allowed values are `project` or `tenant` or `project`

### Read-Only

- `id` (String) The ID of this resource.

<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`

Optional:

- `create` (String)
- `delete` (String)
- `update` (String)
28 changes: 28 additions & 0 deletions examples/resources/spectrocloud_role/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
terraform {
required_providers {
spectrocloud = {
version = ">= 0.1"
source = "spectrocloud/spectrocloud"
}
}
}

variable "sc_host" {
description = "Spectro Cloud Endpoint"
default = "api.spectrocloud.com"
}

variable "sc_api_key" {
description = "Spectro Cloud API key"
}

variable "sc_project_name" {
description = "Spectro Cloud Project (e.g: Default)"
default = "Default"
}

provider "spectrocloud" {
host = var.sc_host
api_key = var.sc_api_key
project_name = var.sc_project_name
}
16 changes: 16 additions & 0 deletions examples/resources/spectrocloud_role/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
variable "roles" {
type = list(string)
default = ["Cluster Admin", "Cluster Profile Editor"]
}

# Data source loop to retrieve multiple roles
data "spectrocloud_role" "roles" {
for_each = toset(var.roles)
name = each.key
}

resource "spectrocloud_role" "custom_role" {
name = "Test Cluster Role"
type = "project"
permissions = flatten([for role in data.spectrocloud_role.roles : role.permissions])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Spectro Cloud credentials
sc_host = "{Enter Spectro Cloud API Host}" #e.g: api.spectrocloud.com (for SaaS)
sc_api_key = "{Enter Spectro Cloud API Key}"
sc_project_name = "{Enter Spectro Cloud Project Name}" #e.g: Default
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/robfig/cron v1.2.0
github.com/spectrocloud/gomi v1.14.1-0.20240214074114-c19394812368
github.com/spectrocloud/hapi v1.14.1-0.20240214071352-81f589b1d86d
github.com/spectrocloud/palette-sdk-go v0.0.0-20241113133445-a5e87250e68d
github.com/spectrocloud/palette-sdk-go v0.0.0-20241113152438-58866fb1d5b7
github.com/stretchr/testify v1.9.0
gotest.tools v2.2.0+incompatible
k8s.io/api v0.23.5
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -600,8 +600,8 @@ github.com/spectrocloud/gomi v1.14.1-0.20240214074114-c19394812368 h1:eY0BOyEbGu
github.com/spectrocloud/gomi v1.14.1-0.20240214074114-c19394812368/go.mod h1:LlZ9We4kDaELYi7Is0SVmnySuDhwphJLS6ZT4wXxFIk=
github.com/spectrocloud/hapi v1.14.1-0.20240214071352-81f589b1d86d h1:OMRbHxMJ1a+G1BYzvUYuMM0wLkYJPdnEOFx16faQ/UY=
github.com/spectrocloud/hapi v1.14.1-0.20240214071352-81f589b1d86d/go.mod h1:MktpRPnSXDTHsQrFSD+daJFQ1zMLSR+1gWOL31jVvWE=
github.com/spectrocloud/palette-sdk-go v0.0.0-20241113133445-a5e87250e68d h1:RkU8p4K15zpH1FB2roV3yrpLiKn+/FcRxuxyJrXmtsk=
github.com/spectrocloud/palette-sdk-go v0.0.0-20241113133445-a5e87250e68d/go.mod h1:dSlNvDS0qwUWTbrYI6P8x981mcbbRHFrBg67v5zl81U=
github.com/spectrocloud/palette-sdk-go v0.0.0-20241113152438-58866fb1d5b7 h1:6qWLXVkq5Ry4tOt1pALAlEz4no8i5XS4SxB8IZEYq6k=
github.com/spectrocloud/palette-sdk-go v0.0.0-20241113152438-58866fb1d5b7/go.mod h1:dSlNvDS0qwUWTbrYI6P8x981mcbbRHFrBg67v5zl81U=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
Expand Down
1 change: 1 addition & 0 deletions spectrocloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ func New(_ string) func() *schema.Provider {
"spectrocloud_workspace": resourceWorkspace(),
"spectrocloud_alert": resourceAlert(),
"spectrocloud_ssh_key": resourceSSHKey(),
"spectrocloud_role": resourceRole(),
},
DataSourcesMap: map[string]*schema.Resource{
"spectrocloud_user": dataSourceUser(),
Expand Down
148 changes: 148 additions & 0 deletions spectrocloud/resource_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package spectrocloud

import (
"context"
"fmt"
"github.com/spectrocloud/palette-sdk-go/api/models"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func resourceRole() *schema.Resource {
return &schema.Resource{
CreateContext: resourceRoleCreate,
ReadContext: resourceRoleRead,
UpdateContext: resourceRoleUpdate,
DeleteContext: resourceRoleDelete,
Description: "The role resource allows you to manage roles in Palette.",

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(10 * time.Minute),
Update: schema.DefaultTimeout(10 * time.Minute),
Delete: schema.DefaultTimeout(10 * time.Minute),
},
SchemaVersion: 2,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "The name of the role.",
},
"type": {
Type: schema.TypeString,
Optional: true,
Default: "project",
ValidateFunc: validation.StringInSlice([]string{"project", "tenant", "resource"}, false),
Description: "The role type. Allowed values are `project` or `tenant` or `project`",
},
"permissions": {
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
Description: "The permission's assigned to the role.",
},
},
}
}

func convertInterfaceSliceToStringSlice(input []interface{}) ([]string, error) {
var output []string
for _, item := range input {
str, ok := item.(string)
if !ok {
return nil, fmt.Errorf("item %v is not a string", item)
}
output = append(output, str)
}
return output, nil
}

func toRole(d *schema.ResourceData) *models.V1Role {
name := d.Get("name").(string)
roleType := d.Get("type").(string)
permission, _ := convertInterfaceSliceToStringSlice(d.Get("permissions").(*schema.Set).List())
return &models.V1Role{
Metadata: &models.V1ObjectMeta{
Annotations: map[string]string{
"scope": roleType,
},
LastModifiedTimestamp: models.V1Time{},
Name: name,
},
Spec: &models.V1RoleSpec{
Permissions: permission,
Scope: models.V1Scope(roleType),
Type: "user",
},
Status: &models.V1RoleStatus{
IsEnabled: true,
},
}
}

func flattenRole(d *schema.ResourceData, role *models.V1Role) error {
var err error
err = d.Set("name", role.Metadata.Name)
if err != nil {
return err
}
err = d.Set("type", role.Spec.Scope)
if err != nil {
return err
}
err = d.Set("permissions", role.Spec.Permissions)
if err != nil {
return err
}
return nil
}

func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := getV1ClientWithResourceContext(m, "tenant")
var diags diag.Diagnostics
role := toRole(d)
uid, err := c.CreateRole(role)
if err != nil {
return diag.FromErr(err)
}
d.SetId(uid)
return diags
}

func resourceRoleRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := getV1ClientWithResourceContext(m, "tenant")
var diags diag.Diagnostics
role, err := c.GetRoleByID(d.Id())
if err != nil {
return diag.FromErr(err)
}
err = flattenRole(d, role)
if err != nil {
return diag.FromErr(err)
}
return diags
}

func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := getV1ClientWithResourceContext(m, "tenant")
var diags diag.Diagnostics
role := toRole(d)
err := c.UpdateRole(role, d.Id())
if err != nil {
return diag.FromErr(err)
}
return diags
}

func resourceRoleDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := getV1ClientWithResourceContext(m, "tenant")
var diags diag.Diagnostics
err := c.DeleteRole(d.Id())
if err != nil {
return diag.FromErr(err)
}
return diags
}
36 changes: 36 additions & 0 deletions templates/resources/role.md.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
subcategory: ""
description: |-
{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
---

# {{.Name}} ({{.Type}})

{{ .Description | plainmarkdown | trimspace | prefixlines " " }}

You can learn more about managing roles in Palette by reviewing the [Roles](https://docs.spectrocloud.com/glossary-all/#role) guide.

## Example Usage

```terraform
variable "roles" {
type = list(string)
default = ["Cluster Admin", "Cluster Profile Editor"]
}

# Data source loop to retrieve multiple roles
data "spectrocloud_role" "roles" {
for_each = toset(var.roles)
name = each.key
}

resource "spectrocloud_role" "custom_role" {
name = "Test Cluster Role"
type = "project"
permissions = flatten([for role in data.spectrocloud_role.roles : role.permissions])
}
```


{{ .SchemaMarkdown | trimspace }}

0 comments on commit ef57d9c

Please sign in to comment.