Skip to content

Commit

Permalink
Support setting metadata in the Frontegg Tenant Resource (#123)
Browse files Browse the repository at this point in the history
* Support setting metadata in the Frontegg Tenant Resource

* lint fixes

---------

Co-authored-by: mariavlasov <[email protected]>
  • Loading branch information
rjobanp and mariavlasov authored Nov 12, 2023
1 parent 44c4573 commit 2dbbc3c
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/resources/tenant.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Configures a Frontegg tenant.
### Optional

- `application_uri` (String) The application URI for this tenant.
- `selected_metadata` (Map of String) Metadata to set and manage; will be merged with upstream metadata fields set outside of terraform.

### Read-Only

Expand Down
9 changes: 9 additions & 0 deletions examples/basic/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,15 @@ resource "frontegg_role" "example" {
]
}

resource "frontegg_tenant" "example" {
name = "Example"
key = "example-tenant-id"

selected_metadata = {
"selected_metadata_key" : "selected_metadata_value",
}
}

output "public_key" {
value = resource.frontegg_workspace.example.auth_policy.0.jwt_public_key
}
80 changes: 80 additions & 0 deletions provider/resource_frontegg_tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package provider

import (
"context"
"encoding/json"
"fmt"

"github.com/frontegg/terraform-provider-frontegg/internal/restclient"
Expand All @@ -15,6 +16,13 @@ type fronteggTenant struct {
Key string `json:"tenantId,omitempty"`
Name string `json:"name,omitempty"`
ApplicationUri string `json:"applicationUrl,omitempty"`
// `Metadata` is only populated when deserializing an API response from JSON,
// since metadata is returned as a jsonified-string.
Metadata string `json:"metadata,omitempty"`
}

type fronteggTenantMetadata struct {
Metadata map[string]string `json:"metadata,omitempty"`
}

func resourceFronteggTenant() *schema.Resource {
Expand Down Expand Up @@ -46,6 +54,14 @@ func resourceFronteggTenant() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"selected_metadata": {
Description: "Metadata to set and manage; will be merged with upstream metadata fields set outside of terraform.",
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}
Expand All @@ -55,6 +71,7 @@ func resourceFronteggTenantSerialize(d *schema.ResourceData) fronteggTenant {
Name: d.Get("name").(string),
Key: d.Get("key").(string),
ApplicationUri: d.Get("application_uri").(string),
// Don't serialize 'Metadata' here, since it will overwrite all upstream metadata.
}
}

Expand All @@ -69,6 +86,33 @@ func resourceFronteggTenantDeserialize(d *schema.ResourceData, f fronteggTenant)
if err := d.Set("application_uri", f.ApplicationUri); err != nil {
return err
}

if len(f.Metadata) > 0 {
if err := resourceFronteggTenantMetadataDeserialize(d, f.Metadata); err != nil {
return err
}
}
return nil
}

func resourceFronteggTenantMetadataDeserialize(d *schema.ResourceData, metadata string) error {
// We only manage keys that are explicitly selected.
selectedMetadata := castResourceStringMap(d.Get("selected_metadata"))
var allUpstreamMetadata map[string]string
if err := json.Unmarshal([]byte(metadata), &allUpstreamMetadata); err != nil {
return err
}
for key := range selectedMetadata {
if newValue, ok := allUpstreamMetadata[key]; ok {
selectedMetadata[key] = newValue
} else {
delete(selectedMetadata, key)
}
}
if err := d.Set("selected_metadata", selectedMetadata); err != nil {
return err
}

return nil
}

Expand All @@ -82,6 +126,18 @@ func resourceFronteggTenantCreate(ctx context.Context, d *schema.ResourceData, m
if err := resourceFronteggTenantDeserialize(d, out); err != nil {
return diag.FromErr(err)
}

// Metadata:
if selectedMetadata, is_set := d.GetOk("selected_metadata"); is_set {
in := fronteggTenantMetadata{castResourceStringMap(selectedMetadata)}
var out fronteggTenant
if err := clientHolder.ApiClient.Post(ctx, fmt.Sprintf("%s/%s/metadata", fronteggTenantPath, d.Id()), in, &out); err != nil {
return diag.FromErr(err)
}
if err := resourceFronteggTenantMetadataDeserialize(d, out.Metadata); err != nil {
return diag.FromErr(err)
}
}
return nil
}

Expand All @@ -105,6 +161,30 @@ func resourceFronteggTenantRead(ctx context.Context, d *schema.ResourceData, met

func resourceFronteggTenantUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
clientHolder := meta.(*restclient.ClientHolder)

// Metadata:
if d.HasChange("selected_metadata") {
oldMetadata, newMetadata := d.GetChange("selected_metadata")
newMetadataAsStringMap := castResourceStringMap(newMetadata)
for key := range castResourceStringMap(oldMetadata) {
if _, ok := newMetadataAsStringMap[key]; !ok {
if err := clientHolder.ApiClient.Delete(ctx, fmt.Sprintf("%s/%s/metadata/%s", fronteggTenantPath, d.Id(), key), nil); err != nil {
return diag.FromErr(err)
}
}
}

// Update all the keys in newMeta
in := fronteggTenantMetadata{newMetadataAsStringMap}
var out fronteggTenant
if err := clientHolder.ApiClient.Post(ctx, fmt.Sprintf("%s/%s/metadata", fronteggTenantPath, d.Id()), in, &out); err != nil {
return diag.FromErr(err)
}
if err := resourceFronteggTenantMetadataDeserialize(d, out.Metadata); err != nil {
return diag.FromErr(err)
}
}

var out fronteggTenant
in := resourceFronteggTenantSerialize(d)
if err := clientHolder.ApiClient.Put(ctx, fmt.Sprintf("%s/%s", fronteggTenantPath, d.Id()), in, &out); err != nil {
Expand Down
8 changes: 8 additions & 0 deletions provider/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ func stringSetToList(set *schema.Set) []string {
}
return out
}

func castResourceStringMap(resourceMapValue interface{}) map[string]string {
newStringMap := make(map[string]string)
for key, val := range resourceMapValue.(map[string]interface{}) {
newStringMap[key] = val.(string)
}
return newStringMap
}

0 comments on commit 2dbbc3c

Please sign in to comment.