Skip to content

Commit 8c94046

Browse files
authored
Merge pull request #44934 from subham-ibmhc/r/aws_connect_routing_profile
Add support for concurrency cross channel behaviour
2 parents b34ec20 + 5a58093 commit 8c94046

File tree

7 files changed

+324
-34
lines changed

7 files changed

+324
-34
lines changed

.changelog/44934.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:enhancement
2+
resource/aws_connect_routing_profile: Add `media_concurrencies.cross_channel_behavior` argument
3+
```
4+
5+
```release-note:enhancement
6+
data-source/aws_connect_routing_profile: Add `media_concurrencies.cross_channel_behavior` attribute
7+
```

internal/service/connect/connect_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ func TestAccConnect_serial(t *testing.T) {
128128
acctest.CtDisappears: testAccRoutingProfile_disappears,
129129
"tags": testAccRoutingProfile_updateTags,
130130
"concurrency": testAccRoutingProfile_updateConcurrency,
131+
"crossChannelBehavior": testAccRoutingProfile_crossChannelBehavior,
131132
"defaultOutboundQueue": testAccRoutingProfile_updateDefaultOutboundQueue,
132133
"queues": testAccRoutingProfile_updateQueues,
133134
"createQueueBatchAssociations": testAccRoutingProfile_createQueueConfigsBatchedAssociateDisassociate,

internal/service/connect/routing_profile.go

Lines changed: 97 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ func resourceRoutingProfile() *schema.Resource {
7878
Required: true,
7979
ValidateFunc: validation.IntBetween(1, 10),
8080
},
81+
"cross_channel_behavior": {
82+
Type: schema.TypeList,
83+
Optional: true,
84+
MaxItems: 1,
85+
Elem: &schema.Resource{
86+
Schema: map[string]*schema.Schema{
87+
"behavior_type": {
88+
Type: schema.TypeString,
89+
Required: true,
90+
ValidateDiagFunc: enum.Validate[awstypes.BehaviorType](),
91+
},
92+
},
93+
},
94+
},
8195
},
8296
},
8397
},
@@ -138,7 +152,7 @@ func resourceRoutingProfileCreate(ctx context.Context, d *schema.ResourceData, m
138152

139153
instanceID := d.Get(names.AttrInstanceID).(string)
140154
name := d.Get(names.AttrName).(string)
141-
input := &connect.CreateRoutingProfileInput{
155+
input := connect.CreateRoutingProfileInput{
142156
DefaultOutboundQueueId: aws.String(d.Get("default_outbound_queue_id").(string)),
143157
Description: aws.String(d.Get(names.AttrDescription).(string)),
144158
InstanceId: aws.String(instanceID),
@@ -156,7 +170,7 @@ func resourceRoutingProfileCreate(ctx context.Context, d *schema.ResourceData, m
156170
input.QueueConfigs = queueConfigs
157171
}
158172

159-
output, err := conn.CreateRoutingProfile(ctx, input)
173+
output, err := conn.CreateRoutingProfile(ctx, &input)
160174

161175
if err != nil {
162176
return sdkdiag.AppendErrorf(diags, "creating Connect Routing Profile (%s): %s", name, err)
@@ -185,7 +199,7 @@ func resourceRoutingProfileRead(ctx context.Context, d *schema.ResourceData, met
185199
return sdkdiag.AppendFromErr(diags, err)
186200
}
187201

188-
routingProfile, err := findRoutingProfileByTwoPartKey(ctx, conn, instanceID, routingProfileID)
202+
output, err := findRoutingProfileByTwoPartKey(ctx, conn, instanceID, routingProfileID)
189203

190204
if !d.IsNewResource() && tfresource.NotFound(err) {
191205
log.Printf("[WARN] Connect Routing Profile (%s) not found, removing from state", d.Id())
@@ -197,15 +211,15 @@ func resourceRoutingProfileRead(ctx context.Context, d *schema.ResourceData, met
197211
return sdkdiag.AppendErrorf(diags, "reading Connect Routing Profile (%s): %s", d.Id(), err)
198212
}
199213

200-
d.Set(names.AttrARN, routingProfile.RoutingProfileArn)
201-
d.Set("default_outbound_queue_id", routingProfile.DefaultOutboundQueueId)
202-
d.Set(names.AttrDescription, routingProfile.Description)
214+
d.Set(names.AttrARN, output.RoutingProfileArn)
215+
d.Set("default_outbound_queue_id", output.DefaultOutboundQueueId)
216+
d.Set(names.AttrDescription, output.Description)
203217
d.Set(names.AttrInstanceID, instanceID)
204-
if err := d.Set("media_concurrencies", flattenMediaConcurrencies(routingProfile.MediaConcurrencies)); err != nil {
218+
if err := d.Set("media_concurrencies", flattenMediaConcurrencies(output.MediaConcurrencies, d.Get("media_concurrencies").(*schema.Set).List())); err != nil {
205219
return sdkdiag.AppendErrorf(diags, "setting media_concurrencies: %s", err)
206220
}
207-
d.Set(names.AttrName, routingProfile.Name)
208-
d.Set("routing_profile_id", routingProfile.RoutingProfileId)
221+
d.Set(names.AttrName, output.Name)
222+
d.Set("routing_profile_id", output.RoutingProfileId)
209223

210224
queueConfigs, err := findRoutingConfigQueueConfigSummariesByTwoPartKey(ctx, conn, instanceID, routingProfileID)
211225

@@ -217,7 +231,7 @@ func resourceRoutingProfileRead(ctx context.Context, d *schema.ResourceData, met
217231
return sdkdiag.AppendErrorf(diags, "setting queue_configs: %s", err)
218232
}
219233

220-
setTagsOut(ctx, routingProfile.Tags)
234+
setTagsOut(ctx, output.Tags)
221235

222236
return diags
223237
}
@@ -239,13 +253,13 @@ func resourceRoutingProfileUpdate(ctx context.Context, d *schema.ResourceData, m
239253

240254
if d.HasChange("media_concurrencies") {
241255
// updates to concurrency
242-
input := &connect.UpdateRoutingProfileConcurrencyInput{
256+
input := connect.UpdateRoutingProfileConcurrencyInput{
243257
InstanceId: aws.String(instanceID),
244258
MediaConcurrencies: expandMediaConcurrencies(d.Get("media_concurrencies").(*schema.Set).List()),
245259
RoutingProfileId: aws.String(routingProfileID),
246260
}
247261

248-
_, err = conn.UpdateRoutingProfileConcurrency(ctx, input)
262+
_, err = conn.UpdateRoutingProfileConcurrency(ctx, &input)
249263

250264
if err != nil {
251265
return sdkdiag.AppendErrorf(diags, "updating Connect Routing Profile (%s) Concurrency: %s", d.Id(), err)
@@ -254,13 +268,13 @@ func resourceRoutingProfileUpdate(ctx context.Context, d *schema.ResourceData, m
254268

255269
if d.HasChange("default_outbound_queue_id") {
256270
// updates to default outbound queue id
257-
input := &connect.UpdateRoutingProfileDefaultOutboundQueueInput{
271+
input := connect.UpdateRoutingProfileDefaultOutboundQueueInput{
258272
DefaultOutboundQueueId: aws.String(d.Get("default_outbound_queue_id").(string)),
259273
InstanceId: aws.String(instanceID),
260274
RoutingProfileId: aws.String(routingProfileID),
261275
}
262276

263-
_, err = conn.UpdateRoutingProfileDefaultOutboundQueue(ctx, input)
277+
_, err = conn.UpdateRoutingProfileDefaultOutboundQueue(ctx, &input)
264278

265279
if err != nil {
266280
return sdkdiag.AppendErrorf(diags, "updating Connect Routing Profile (%s) DefaultOutboundQueue: %s", d.Id(), err)
@@ -269,14 +283,14 @@ func resourceRoutingProfileUpdate(ctx context.Context, d *schema.ResourceData, m
269283

270284
if d.HasChanges(names.AttrName, names.AttrDescription) {
271285
// updates to name and/or description
272-
input := &connect.UpdateRoutingProfileNameInput{
286+
input := connect.UpdateRoutingProfileNameInput{
273287
Description: aws.String(d.Get(names.AttrDescription).(string)),
274288
InstanceId: aws.String(instanceID),
275289
Name: aws.String(d.Get(names.AttrName).(string)),
276290
RoutingProfileId: aws.String(routingProfileID),
277291
}
278292

279-
_, err = conn.UpdateRoutingProfileName(ctx, input)
293+
_, err = conn.UpdateRoutingProfileName(ctx, &input)
280294

281295
if err != nil {
282296
return sdkdiag.AppendErrorf(diags, "updating Connect Routing Profile (%s) Name: %s", d.Id(), err)
@@ -368,13 +382,13 @@ func updateRoutingProfileQueueAssociations(ctx context.Context, conn *connect.Cl
368382
}
369383

370384
if len(queueReferences) > 0 {
371-
input := &connect.DisassociateRoutingProfileQueuesInput{
385+
input := connect.DisassociateRoutingProfileQueuesInput{
372386
InstanceId: aws.String(instanceID),
373387
QueueReferences: queueReferences,
374388
RoutingProfileId: aws.String(routingProfileID),
375389
}
376390

377-
_, err := conn.DisassociateRoutingProfileQueues(ctx, input)
391+
_, err := conn.DisassociateRoutingProfileQueues(ctx, &input)
378392

379393
if err != nil {
380394
return fmt.Errorf("disassociating Connect Routing Profile (%s) queues: %w", routingProfileID, err)
@@ -383,13 +397,13 @@ func updateRoutingProfileQueueAssociations(ctx context.Context, conn *connect.Cl
383397
}
384398

385399
for chunk := range slices.Chunk(add, routingProfileQueueAssociationChunkSize) {
386-
input := &connect.AssociateRoutingProfileQueuesInput{
400+
input := connect.AssociateRoutingProfileQueuesInput{
387401
InstanceId: aws.String(instanceID),
388402
QueueConfigs: chunk,
389403
RoutingProfileId: aws.String(routingProfileID),
390404
}
391405

392-
_, err := conn.AssociateRoutingProfileQueues(ctx, input)
406+
_, err := conn.AssociateRoutingProfileQueues(ctx, &input)
393407

394408
if err != nil {
395409
return fmt.Errorf("associating Connect Routing Profile (%s) queues: %w", routingProfileID, err)
@@ -400,12 +414,12 @@ func updateRoutingProfileQueueAssociations(ctx context.Context, conn *connect.Cl
400414
}
401415

402416
func findRoutingProfileByTwoPartKey(ctx context.Context, conn *connect.Client, instanceID, routingProfileID string) (*awstypes.RoutingProfile, error) {
403-
input := &connect.DescribeRoutingProfileInput{
417+
input := connect.DescribeRoutingProfileInput{
404418
InstanceId: aws.String(instanceID),
405419
RoutingProfileId: aws.String(routingProfileID),
406420
}
407421

408-
return findRoutingProfile(ctx, conn, input)
422+
return findRoutingProfile(ctx, conn, &input)
409423
}
410424

411425
func findRoutingProfile(ctx context.Context, conn *connect.Client, input *connect.DescribeRoutingProfileInput) (*awstypes.RoutingProfile, error) {
@@ -431,13 +445,13 @@ func findRoutingProfile(ctx context.Context, conn *connect.Client, input *connec
431445

432446
func findRoutingConfigQueueConfigSummariesByTwoPartKey(ctx context.Context, conn *connect.Client, instanceID, routingProfileID string) ([]awstypes.RoutingProfileQueueConfigSummary, error) {
433447
const maxResults = 60
434-
input := &connect.ListRoutingProfileQueuesInput{
448+
input := connect.ListRoutingProfileQueuesInput{
435449
InstanceId: aws.String(instanceID),
436450
MaxResults: aws.Int32(maxResults),
437451
RoutingProfileId: aws.String(routingProfileID),
438452
}
439453

440-
return findRoutingConfigQueueConfigSummaries(ctx, conn, input)
454+
return findRoutingConfigQueueConfigSummaries(ctx, conn, &input)
441455
}
442456

443457
func findRoutingConfigQueueConfigSummaries(ctx context.Context, conn *connect.Client, input *connect.ListRoutingProfileQueuesInput) ([]awstypes.RoutingProfileQueueConfigSummary, error) {
@@ -477,13 +491,18 @@ func expandMediaConcurrencies(tfList []any) []awstypes.MediaConcurrency {
477491
Channel: awstypes.Channel(tfMap["channel"].(string)),
478492
Concurrency: aws.Int32(int32(tfMap["concurrency"].(int))),
479493
}
494+
495+
if v, ok := tfMap["cross_channel_behavior"].([]any); ok && len(v) > 0 {
496+
apiObject.CrossChannelBehavior = expandCrossChannelBehavior(v)
497+
}
498+
480499
apiObjects = append(apiObjects, apiObject)
481500
}
482501

483502
return apiObjects
484503
}
485504

486-
func flattenMediaConcurrencies(apiObjects []awstypes.MediaConcurrency) []any {
505+
func flattenMediaConcurrencies(apiObjects []awstypes.MediaConcurrency, mediaConcurrencyCfg []any) []any {
487506
tfList := []any{}
488507

489508
for _, apiObject := range apiObjects {
@@ -492,12 +511,43 @@ func flattenMediaConcurrencies(apiObjects []awstypes.MediaConcurrency) []any {
492511
"concurrency": aws.ToInt32(apiObject.Concurrency),
493512
}
494513

514+
// Only write cross_channel_behavior to state when explicitly configured
515+
channel := string(apiObject.Channel)
516+
ccbChannels := channelsWithCrossChannelBehavior(mediaConcurrencyCfg)
517+
if apiObject.CrossChannelBehavior != nil && slices.Contains(ccbChannels, channel) {
518+
tfMap["cross_channel_behavior"] = flattenCrossChannelBehavior(apiObject.CrossChannelBehavior)
519+
}
520+
495521
tfList = append(tfList, tfMap)
496522
}
497523

498524
return tfList
499525
}
500526

527+
func expandCrossChannelBehavior(tfList []any) *awstypes.CrossChannelBehavior {
528+
if len(tfList) == 0 {
529+
return nil
530+
}
531+
532+
tfMap := tfList[0].(map[string]any)
533+
534+
return &awstypes.CrossChannelBehavior{
535+
BehaviorType: awstypes.BehaviorType(tfMap["behavior_type"].(string)),
536+
}
537+
}
538+
539+
func flattenCrossChannelBehavior(apiObject *awstypes.CrossChannelBehavior) []map[string]any {
540+
if apiObject == nil {
541+
return nil
542+
}
543+
544+
return []map[string]any{
545+
{
546+
"behavior_type": string(apiObject.BehaviorType),
547+
},
548+
}
549+
}
550+
501551
func expandRoutingProfileQueueConfigs(tfList []any) []awstypes.RoutingProfileQueueConfig {
502552
if len(tfList) == 0 {
503553
return nil
@@ -540,3 +590,25 @@ func flattenRoutingConfigQueueConfigSummaries(apiObjects []awstypes.RoutingProfi
540590

541591
return tfList
542592
}
593+
594+
// channelsWithCrossChannelBehavior returns a list of channel names which have
595+
// cross_channel_behavior set
596+
//
597+
// This data structure can be used to determine when to write the remote cross_channel_behavior
598+
// value to state. Writing the value when a corresponding congiuration is not present
599+
// will trigger persistent drift as the object is nested within a required set attribute.
600+
func channelsWithCrossChannelBehavior(cfgList []any) []string {
601+
var c []string
602+
for _, l := range cfgList {
603+
m := l.(map[string]any)
604+
if m == nil {
605+
continue
606+
}
607+
608+
if v, ok := m["cross_channel_behavior"].([]any); ok && len(v) > 0 {
609+
c = append(c, m["channel"].(string))
610+
}
611+
}
612+
613+
return c
614+
}

internal/service/connect/routing_profile_data_source.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ func dataSourceRoutingProfile() *schema.Resource {
5959
Type: schema.TypeInt,
6060
Computed: true,
6161
},
62+
"cross_channel_behavior": {
63+
Type: schema.TypeList,
64+
Computed: true,
65+
Elem: &schema.Resource{
66+
Schema: map[string]*schema.Schema{
67+
"behavior_type": {
68+
Type: schema.TypeString,
69+
Computed: true,
70+
},
71+
},
72+
},
73+
},
6274
},
6375
},
6476
},
@@ -146,7 +158,7 @@ func dataSourceRoutingProfileRead(ctx context.Context, d *schema.ResourceData, m
146158
d.Set("default_outbound_queue_id", routingProfile.DefaultOutboundQueueId)
147159
d.Set(names.AttrDescription, routingProfile.Description)
148160
d.Set(names.AttrInstanceID, instanceID)
149-
if err := d.Set("media_concurrencies", flattenMediaConcurrencies(routingProfile.MediaConcurrencies)); err != nil {
161+
if err := d.Set("media_concurrencies", flattenMediaConcurrencies(routingProfile.MediaConcurrencies, d.Get("media_concurrencies").(*schema.Set).List())); err != nil {
150162
return sdkdiag.AppendErrorf(diags, "setting media_concurrencies: %s", err)
151163
}
152164
d.Set(names.AttrName, routingProfile.Name)

0 commit comments

Comments
 (0)