Skip to content

Commit

Permalink
Add user attribute member resource (#44)
Browse files Browse the repository at this point in the history
* Add user attribute member resource

* Documentation generation

* Remove import method; N/A
  • Loading branch information
Nabil-Lahssini authored Mar 27, 2023
1 parent e7be987 commit 7c7e020
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 1 deletion.
91 changes: 91 additions & 0 deletions docs/resources/user_attribute_member.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
page_title: "looker_user_attribute_member Resource - terraform-provider-looker"
subcategory: ""
description: |-
---
# looker_user_attribute_member (Resource)

## Example Usage
```terraform
resource "looker_user_attribute" "att" {
name = "attribute_name"
label = "attribute label"
type = "string"
}
resource "looker_group" "my-group" {
name = "mygroup"
}
resource "looker_user_attribute_member" "name" {
user_attribute_id = looker_user_attribute.att.id
group {
id = looker_group.my-group.id
value = "attribute-value"
}
}
```

## Example Output
```terraform
% terraform show
# looker_group.my-group:
resource "looker_group" "my-group" {
delete_on_destroy = true
id = "39"
name = "mygroup"
parent_groups = []
roles = []
}
# looker_user_attribute.att:
resource "looker_user_attribute" "att" {
id = "35"
label = "attribute label"
name = "attribute_name"
type = "string"
user_can_edit = true
user_can_view = true
value_is_hidden = false
}
# looker_user_attribute_member.name:
resource "looker_user_attribute_member" "name" {
id = "-"
user_attribute_id = "35"
group {
id = "39"
name = "mygroup"
value = "attribute-value"
}
}
```

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

### Required

- `user_attribute_id` (String)

### Optional

- `group` (Block Set) (see [below for nested schema](#nestedblock--group))

### Read-Only

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

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

Required:

- `value` (String)

Read-Only:

- `id` (String) The ID of this resource.
- `name` (String)
17 changes: 17 additions & 0 deletions examples/resources/looker_user_attribute_member/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
resource "looker_user_attribute" "att" {
name = "attribute_name"
label = "attribute label"
type = "string"
}

resource "looker_group" "my-group" {
name = "mygroup"
}

resource "looker_user_attribute_member" "name" {
user_attribute_id = looker_user_attribute.att.id
group {
id = looker_group.my-group.id
value = "attribute-value"
}
}
32 changes: 32 additions & 0 deletions examples/resources/looker_user_attribute_member/resource.tfshow
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
% terraform show
# looker_group.my-group:
resource "looker_group" "my-group" {
delete_on_destroy = true
id = "39"
name = "mygroup"
parent_groups = []
roles = []
}

# looker_user_attribute.att:
resource "looker_user_attribute" "att" {
id = "35"
label = "attribute label"
name = "attribute_name"
type = "string"
user_can_edit = true
user_can_view = true
value_is_hidden = false
}

# looker_user_attribute_member.name:
resource "looker_user_attribute_member" "name" {
id = "-"
user_attribute_id = "35"

group {
id = "39"
name = "mygroup"
value = "attribute-value"
}
}
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func New(version string) func() *schema.Provider {
"looker_color_collection": resourceColorCollection(),
"looker_permission_set": resourcePermissionSet(),
"looker_user_attribute": resourceUserAttribute(),
"looker_user_attribute_member": resourceUserAttributeMember(),
},
}

Expand Down
1 change: 1 addition & 0 deletions internal/provider/resource_user_attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,6 @@ func resourceUserAttributeDelete(ctx context.Context, d *schema.ResourceData, m
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return diags
}
128 changes: 128 additions & 0 deletions internal/provider/resource_user_attribute_member.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package provider

import (
"context"

"github.com/devoteamgcloud/terraform-provider-looker/pkg/lookergo"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceUserAttributeMember() *schema.Resource {
return &schema.Resource{
CreateContext: resourceUserAttributeMemberCreate,
ReadContext: resourceUserAttributeMemberRead,
UpdateContext: resourceUserAttributeMemberUpdate,
DeleteContext: resourceUserAttributeMemberDelete,
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"user_attribute_id": {
Type: schema.TypeString,
Required: true,
},
"group": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Required: true,
},
"value": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}

func resourceUserAttributeMemberCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*Config).Api // .(*lookergo.Client)
var diags diag.Diagnostics
ID := d.Get("user_attribute_id").(string)
groupSet, ok := d.GetOk("group")
userAttrs := []lookergo.UserAttributeGroupValue{}
if ok {
for _, raw := range groupSet.(*schema.Set).List() {
obj := raw.(map[string]interface{})
val := obj["id"].(string)
att := lookergo.UserAttributeGroupValue{}
att.GroupId = val
att.UserAttributeId = d.Get("user_attribute_id").(string)
att.Value = obj["value"].(string)
userAttrs = append(userAttrs, att)
}
}
_, _, err := c.UserAttributes.SetUserAttributeValue(ctx, userAttrs, ID)
if err != nil {
return diag.FromErr(err)
}
d.SetId("-")
resourceUserAttributeMemberRead(ctx, d, m)
return diags
}

func resourceUserAttributeMemberRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*Config).Api // .(*lookergo.Client)
var diags diag.Diagnostics
ID := d.Get("user_attribute_id").(string)
attrs, _, err := c.UserAttributes.GetUserAttributeValue(ctx, ID)
if err != nil {
return diag.FromErr(err)
}
var attrItems []interface{}
for _, attr := range *attrs {
group, _, err := c.Groups.Get(ctx, idAsInt(attr.GroupId))
if err != nil {
return diag.FromErr(err)
}
attrItems = append(attrItems, map[string]interface{}{"id": idAsString(group.Id), "name": group.Name, "value": attr.Value})
}
d.Set("group", attrItems)
return diags
}

func resourceUserAttributeMemberUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*Config).Api // .(*lookergo.Client)
ID := d.Get("user_attribute_id").(string)
groupSet, ok := d.GetOk("group")
userAttrs := []lookergo.UserAttributeGroupValue{}
if ok {
for _, raw := range groupSet.(*schema.Set).List() {
obj := raw.(map[string]interface{})
val := obj["id"].(string)
att := lookergo.UserAttributeGroupValue{}
att.GroupId = val
att.UserAttributeId = d.Get("user_attribute_id").(string)
att.Value = obj["value"].(string)
userAttrs = append(userAttrs, att)
}
}
_, _, err := c.UserAttributes.SetUserAttributeValue(ctx, userAttrs, ID)
if err != nil {
return diag.FromErr(err)
}
d.SetId("-")
return resourceUserAttributeMemberRead(ctx, d, m)
}

func resourceUserAttributeMemberDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*Config).Api // .(*lookergo.Client)
var diags diag.Diagnostics
att := []lookergo.UserAttributeGroupValue{}
ID := d.Get("user_attribute_id").(string)
c.UserAttributes.SetUserAttributeValue(ctx, att, ID)
d.SetId("")
return diags
}
32 changes: 31 additions & 1 deletion pkg/lookergo/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ func StreamToString(stream io.Reader) string {
}

type service interface {
Group | User | CredentialsEmail | Role | PermissionSet | Session | Project | GitBranch | Folder | UserAttribute
Group | User | CredentialsEmail | Role | PermissionSet | Session | Project | GitBranch | Folder | UserAttribute | UserAttributeGroupValue
}

// addOptions -
Expand Down Expand Up @@ -811,6 +811,36 @@ func doAddMember[T service](ctx context.Context, client *Client, path string, sv
return svc, resp, err
}

func doAddValue[T service](ctx context.Context, client *Client, path string, svc *[]T, addNew interface{}) (*[]T, *Response, error) {

req, err := client.NewRequest(ctx, http.MethodPost, path, addNew)
if err != nil {
return nil, nil, err
}

resp, err := client.Do(ctx, req, svc)
if err != nil {
return nil, resp, err
}

return svc, resp, err
}

func doDeleteX(ctx context.Context, client *Client, path string) (*Response, error) {

req, err := client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}

resp, err := client.Do(ctx, req, nil)
if err != nil {
return resp, err
}

return resp, err
}

func boolPtr(b bool) *bool {
return &b
}
23 changes: 23 additions & 0 deletions pkg/lookergo/user_attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package lookergo

import (
"context"
"fmt"
)

type UserAttributesResourceOp struct {
Expand All @@ -25,11 +26,23 @@ type UserAttribute struct {
HiddenValueDomainWhitelist *string `json:"hidden_value_domain_whitelist,omitempty"` // Destinations to which a hidden attribute may be sent. Once set, cannot be edited.
}

type UserAttributeGroupValue struct {
Can map[string]bool `json:"can,omitempty"` // Operations the current user is able to perform on this object
Id string `json:"id,omitempty"` // Unique Id of this group-attribute relation
GroupId string `json:"group_id,omitempty"` // Id of group
UserAttributeId string `json:"user_attribute_id,omitempty"` // Id of user attribute
ValueIsHidden bool `json:"value_is_hidden,omitempty"` // If true, the "value" field will be null, because the attribute settings block access to this value
Rank int64 `json:"rank,omitempty"` // Precedence for resolving value for user
Value string `json:"value,omitempty"` // Value of user attribute for group
}

type UserAttributesResource interface {
Get(context.Context, int) (*UserAttribute, *Response, error)
Create(context.Context, *UserAttribute) (*UserAttribute, *Response, error)
Update(context.Context, string, *UserAttribute) (*UserAttribute, *Response, error)
Delete(context.Context, string) (*Response, error)
SetUserAttributeValue(context.Context, []UserAttributeGroupValue, string) (*[]UserAttributeGroupValue, *Response, error)
GetUserAttributeValue(context.Context, string) (*[]UserAttributeGroupValue, *Response, error)
}

func (s *UserAttributesResourceOp) Get(ctx context.Context, UserAttributeId int) (*UserAttribute, *Response, error) {
Expand All @@ -47,3 +60,13 @@ func (s *UserAttributesResourceOp) Update(ctx context.Context, UserAttributeId s
func (s *UserAttributesResourceOp) Delete(ctx context.Context, UserAttributeId string) (*Response, error) {
return doDelete(ctx, s.client, UserAttributesBasePath, UserAttributeId)
}

func (s *UserAttributesResourceOp) SetUserAttributeValue(ctx context.Context, userAtt []UserAttributeGroupValue, attributeId string) (*[]UserAttributeGroupValue, *Response, error) {
path := fmt.Sprintf("%s/%s/group_values", UserAttributesBasePath, attributeId)
return doAddValue(ctx, s.client, path, new([]UserAttributeGroupValue), userAtt)
}

func (s *UserAttributesResourceOp) GetUserAttributeValue(ctx context.Context, UserAttributeId string) (*[]UserAttributeGroupValue, *Response, error) {
path := fmt.Sprintf("%s/%s/group_values", UserAttributesBasePath, UserAttributeId)
return doGet(ctx, s.client, path, new([]UserAttributeGroupValue))
}

0 comments on commit 7c7e020

Please sign in to comment.