Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions docs/resources/greeting_user.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
page_title: "genesyscloud_greeting_user Resource - terraform-provider-genesyscloud"
subcategory: ""
description: |-
Genesys Cloud Greetings (User)
---
# genesyscloud_greeting_user (Resource)

Genesys Cloud Greetings (User)

## API Usage
The following Genesys Cloud APIs are used by this resource. Ensure your OAuth Client has been granted the necessary scopes and permissions to perform these operations:

* [POST /api/v2/users/{userId}/greetings](https://apicentral.genesys.cloud/api-explorer#post-api-v2-users--userId--greetings)
* [GET /api/v2/greetings/{greetingId}](https://apicentral.genesys.cloud/api-explorer#get-api-v2-greetings--greetingId-)
* [GET /api/v2/users/{userId}/greetings](https://apicentral.genesys.cloud/api-explorer#get-api-v2-users--userId--greetings)
* [PUT /api/v2/greetings/{greetingId}](https://apicentral.genesys.cloud/api-explorer#put-api-v2-greetings--greetingId-)
* [DELETE /api/v2/greetings/{greetingId}](https://apicentral.genesys.cloud/api-explorer#delete-api-v2-greetings--greetingId-)


## Example Usage

```terraform
resource "genesyscloud_user" "ExampleTestUser" {
name = "Example Test User"
email = "example.test.user@example.com"
}

resource "genesyscloud_greeting_user" "Test_Greeting" {
name = "Example Test Greeting"
type = "NAME"
owner_type = "USER"
user_id = genesyscloud_user.ExampleTestUser.id
audio_tts = "This is a test greeting"
}
```

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

### Required

- `owner_type` (String) Greeting owner type. USER is the only supported owner type for user greetings.
- `type` (String) Greeting type. NAME is only supported type for user greetings.

### Optional

- `audio_file` (Block List, Max: 1) Greeting audio file. (see [below for nested schema](#nestedblock--audio_file))
- `audio_tts` (String) Greeting audio TTS.
- `name` (String) Greeting name.
- `user_id` (String) The ID of the user owner of the greeting.

### Read-Only

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

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

Optional:

- `duration_milliseconds` (Number) Greeting audio file duration in milliseconds.
- `self_uri` (String) Greeting audio file self URI.
- `size_bytes` (Number) Greeting audio file size in bytes.
5 changes: 5 additions & 0 deletions examples/resources/genesyscloud_greeting_user/apis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* [POST /api/v2/users/{userId}/greetings](https://apicentral.genesys.cloud/api-explorer#post-api-v2-users--userId--greetings)
* [GET /api/v2/greetings/{greetingId}](https://apicentral.genesys.cloud/api-explorer#get-api-v2-greetings--greetingId-)
* [GET /api/v2/users/{userId}/greetings](https://apicentral.genesys.cloud/api-explorer#get-api-v2-users--userId--greetings)
* [PUT /api/v2/greetings/{greetingId}](https://apicentral.genesys.cloud/api-explorer#put-api-v2-greetings--greetingId-)
* [DELETE /api/v2/greetings/{greetingId}](https://apicentral.genesys.cloud/api-explorer#delete-api-v2-greetings--greetingId-)
12 changes: 12 additions & 0 deletions examples/resources/genesyscloud_greeting_user/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
resource "genesyscloud_user" "ExampleTestUser" {
name = "Example Test User"
email = "example.test.user@example.com"
}

resource "genesyscloud_greeting_user" "Test_Greeting" {
name = "Example Test Greeting"
type = "NAME"
owner_type = "USER"
user_id = genesyscloud_user.ExampleTestUser.id
audio_tts = "This is a test greeting"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package greeting_user

import (
"sync"
"testing"

groupResource "github.com/mypurecloud/terraform-provider-genesyscloud/genesyscloud/group"
userResource "github.com/mypurecloud/terraform-provider-genesyscloud/genesyscloud/user"

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

/*
The genesyscloud_greetings_init_test.go file is used to initialize the data sources and resources
used in testing the greetings resource.
*/

// providerResources holds a map of all registered resources
var providerResources map[string]*schema.Resource

type registerTestInstance struct {
resourceMapMutex sync.RWMutex
datasourceMapMutex sync.RWMutex
}

// registerTestResources registers all resources used in the tests
func (r *registerTestInstance) registerTestResources() {
r.resourceMapMutex.Lock()
defer r.resourceMapMutex.Unlock()

providerResources[userResource.ResourceType] = userResource.ResourceUser()
providerResources[groupResource.ResourceType] = groupResource.ResourceGroup()
providerResources[ResourceType] = ResourceGreeting()
}

// initTestResources initializes all test resources and data sources.
func initTestResources() {
providerResources = make(map[string]*schema.Resource)

regInstance := &registerTestInstance{}

regInstance.registerTestResources()
}

// TestMain is a "setup" function called by the testing framework when run the test
func TestMain(m *testing.M) {
// Run setup function before starting the test suite for greetings package
initTestResources()

// Run the test suite for the greetings package
m.Run()
}
247 changes: 247 additions & 0 deletions genesyscloud/greeting_user/genesyscloud_greeting_user_proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
package greeting_user

import (
"context"
"fmt"
"log"
"net/http"

"github.com/mypurecloud/platform-client-sdk-go/v176/platformclientv2"
rc "github.com/mypurecloud/terraform-provider-genesyscloud/genesyscloud/resource_cache"
"github.com/mypurecloud/terraform-provider-genesyscloud/genesyscloud/tfexporter_state"
)

var internalProxy *greetingProxy
var greetingCache = rc.NewResourceCache[platformclientv2.Greeting]()

type getAllGreetingsFunc func(ctx context.Context, p *greetingProxy) (*[]platformclientv2.Domainentity, *platformclientv2.APIResponse, error)
type getUserGreetingByIdFunc func(ctx context.Context, p *greetingProxy, userId string, id string) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error)
type updateUserGreetingFunc func(ctx context.Context, p *greetingProxy, greetingId string, body *platformclientv2.Greeting) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error)
type createUserGreetingFunc func(ctx context.Context, p *greetingProxy, body *platformclientv2.Greeting) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error)
type deleteUserGreetingFunc func(ctx context.Context, p *greetingProxy, id string) (*platformclientv2.APIResponse, error)

type greetingProxy struct {
clientConfig *platformclientv2.Configuration
greetingsApi *platformclientv2.GreetingsApi
usersApi *platformclientv2.UsersApi
getAllGreetingsAttr getAllGreetingsFunc
createGreetingAttr createUserGreetingFunc
getGreetingByIdAttr getUserGreetingByIdFunc
updateGreetingAttr updateUserGreetingFunc
deleteGreetingAttr deleteUserGreetingFunc
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to implement the cache mechanism for greeting user resource

greetingCache rc.CacheInterface[platformclientv2.Greeting]
}

func newGreetingProxy(clientConfig *platformclientv2.Configuration) *greetingProxy {
api := platformclientv2.NewGreetingsApiWithConfig(clientConfig)
usersApi := platformclientv2.NewUsersApiWithConfig(clientConfig)
return &greetingProxy{
clientConfig: clientConfig,
greetingsApi: api,
usersApi: usersApi,
getAllGreetingsAttr: getAllGreetingsFn,
createGreetingAttr: createUserGreetingFn,
getGreetingByIdAttr: getUserGreetingByIdFn,
updateGreetingAttr: updateUserGreetingFn,
deleteGreetingAttr: deleteUserGreetingFn,
greetingCache: greetingCache,
}
}

func getGreeetingProxy(clientConfig *platformclientv2.Configuration) *greetingProxy {
if internalProxy == nil {
internalProxy = newGreetingProxy(clientConfig)
}

return internalProxy
}

func (p *greetingProxy) getAllGreetings(ctx context.Context) (*[]platformclientv2.Domainentity, *platformclientv2.APIResponse, error) {
return p.getAllGreetingsAttr(ctx, p)
}
func (p *greetingProxy) createUserGreeting(ctx context.Context, body *platformclientv2.Greeting) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error) {
return p.createGreetingAttr(ctx, p, body)
}
func (p *greetingProxy) getUserGreetingById(ctx context.Context, userId string, id string) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error) {
if greeting := rc.GetCacheItem(p.greetingCache, id); greeting != nil {
return greeting, nil, nil
}
return p.getGreetingByIdAttr(ctx, p, userId, id)
}
func (p *greetingProxy) updateUserGreeting(ctx context.Context, greetingID string, body *platformclientv2.Greeting) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error) {
return p.updateGreetingAttr(ctx, p, greetingID, body)
}
func (p *greetingProxy) deleteUserGreeting(ctx context.Context, id string) (*platformclientv2.APIResponse, error) {
rc.DeleteCacheItem(p.greetingCache, id)
return p.deleteGreetingAttr(ctx, p, id)
}
func getAllGreetingsFn(ctx context.Context, p *greetingProxy) (*[]platformclientv2.Domainentity, *platformclientv2.APIResponse, error) {
var allGreetings []platformclientv2.Domainentity
const pageSize = 100
allUsers, resp, err := getAllUsersFn(ctx, p)
if err != nil {
return nil, resp, fmt.Errorf("failed to get users %s", err)
}

for _, user := range *allUsers {
userGreetings, resp, err := p.greetingsApi.GetUserGreetings(*user.Id, pageSize, 1)
if err != nil {
return nil, resp, fmt.Errorf("failed to get greetings for user %s: %s", *user.Id, err)
}
if userGreetings.Entities != nil {
allGreetings = append(allGreetings, *userGreetings.Entities...)
if tfexporter_state.IsExporterActive() {
for _, entity := range *userGreetings.Entities {
if entity.Id == nil {
continue
}
g, _, gErr := p.greetingsApi.GetGreeting(*entity.Id)
if gErr != nil {
log.Printf("failed to cache greeting %s: %v", *entity.Id, gErr)
continue
}
if g != nil && g.Id != nil {
rc.SetCache(p.greetingCache, *g.Id, *g)
}
}
}
}
for pageNum := 2; pageNum <= *userGreetings.PageCount; pageNum++ {
userGreetings, resp, err := p.greetingsApi.GetUserGreetings(*user.Id, pageSize, pageNum)
if err != nil {
return nil, resp, fmt.Errorf("failed to get greetings for user %s: %s", *user.Id, err)
}
if userGreetings.Entities != nil {
allGreetings = append(allGreetings, *userGreetings.Entities...)
if tfexporter_state.IsExporterActive() {
for _, entity := range *userGreetings.Entities {
if entity.Id == nil {
continue
}
g, _, gErr := p.greetingsApi.GetGreeting(*entity.Id)
if gErr != nil {
log.Printf("failed to cache greeting %s: %v", *entity.Id, gErr)
continue
}
if g != nil && g.Id != nil {
rc.SetCache(p.greetingCache, *g.Id, *g)
}
}
}
}
}
}
return &allGreetings, resp, nil
}

func createUserGreetingFn(ctx context.Context, p *greetingProxy, body *platformclientv2.Greeting) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error) {
g, resp, err := p.greetingsApi.PostUserGreetings(*body.Owner.Id, *body)
if err != nil {
return g, resp, err
}
if g != nil && g.Id != nil {
rc.SetCache(p.greetingCache, *g.Id, *g)
}
return g, resp, nil
}
func getUserGreetingByIdFn(ctx context.Context, p *greetingProxy, userId string, id string) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error) {
if tfexporter_state.IsExporterActive() {
log.Printf("Could not read greeting '%s' from cache. Reading from the API...", id)
g, resp, err := p.greetingsApi.GetGreeting(id)
if err != nil {
return g, resp, err
}
if g != nil && g.Id != nil {
rc.SetCache(p.greetingCache, *g.Id, *g)
}
return g, resp, nil
}
if userId == "" {
return p.greetingsApi.GetGreeting(id)
}
return getGreetingFromUser(ctx, p, userId, id)
}

func getGreetingFromUser(ctx context.Context, p *greetingProxy, userId string, id string) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error) {
const pageSize = 100
userGreetings, resp, err := p.greetingsApi.GetUserGreetings(userId, pageSize, 1)
if err != nil {
return nil, resp, err
}
if greeting := findGreetingInEntities(userGreetings.Entities, userId, id); greeting != nil {
return greeting, resp, nil
}

for pageNum := 2; pageNum <= *userGreetings.PageCount; pageNum++ {
userGreetings, resp, err = p.greetingsApi.GetUserGreetings(userId, pageSize, pageNum)
if err != nil {
return nil, resp, err
}
if greeting := findGreetingInEntities(userGreetings.Entities, userId, id); greeting != nil {
return greeting, resp, nil
}
}

return nil, &platformclientv2.APIResponse{StatusCode: http.StatusNotFound}, fmt.Errorf("greeting %s not found for user %s", id, userId)
}

func findGreetingInEntities(entities *[]platformclientv2.Domainentity, userId string, greetingId string) *platformclientv2.Greeting {
if entities == nil {
return nil
}
for _, entity := range *entities {
if entity.Id != nil && *entity.Id == greetingId {
return &platformclientv2.Greeting{
Id: entity.Id,
Name: entity.Name,
VarType: platformclientv2.String("NAME"),
OwnerType: platformclientv2.String("USER"),
Owner: &platformclientv2.Domainentity{
Id: platformclientv2.String(userId),
},
}
}
}
return nil
}
func updateUserGreetingFn(ctx context.Context, p *greetingProxy, greetingId string, body *platformclientv2.Greeting) (*platformclientv2.Greeting, *platformclientv2.APIResponse, error) {
g, resp, err := p.greetingsApi.PutGreeting(greetingId, *body)
if err != nil {
return g, resp, err
}
if g != nil && g.Id != nil {
rc.SetCache(p.greetingCache, *g.Id, *g)
}
return g, resp, nil
}
func deleteUserGreetingFn(ctx context.Context, p *greetingProxy, id string) (*platformclientv2.APIResponse, error) {
return p.greetingsApi.DeleteGreeting(id)
}
func getAllUsersFn(ctx context.Context, p *greetingProxy) (*[]platformclientv2.User, *platformclientv2.APIResponse, error) {
var allUsers []platformclientv2.User
const pageSize = 100

users, resp, err := p.usersApi.GetUsers(pageSize, 1, nil, nil, "", nil, "", "")
if err != nil {
return nil, resp, fmt.Errorf("failed to get users %s", err)
}

if users.Entities == nil || len(*users.Entities) == 0 {
return &allUsers, resp, nil
}
allUsers = append(allUsers, *users.Entities...)

for pageNum := 2; pageNum <= *users.PageCount; pageNum++ {
users, resp, err := p.usersApi.GetUsers(pageSize, pageNum, nil, nil, "", nil, "", "")
if err != nil {
return nil, resp, fmt.Errorf("failed to get users %s", err)
}

if users.Entities == nil || len(*users.Entities) == 0 {
return &allUsers, resp, nil
}

allUsers = append(allUsers, *users.Entities...)
}
return &allUsers, resp, nil
}
Loading