@@ -2,18 +2,21 @@ package provider
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"fmt"
6
7
"strings"
7
8
8
9
"github.com/segmentio/terraform-provider-segment/internal/provider/docs"
9
10
"github.com/segmentio/terraform-provider-segment/internal/provider/models"
10
11
11
12
"github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes"
13
+ "github.com/hashicorp/terraform-plugin-framework/diag"
12
14
"github.com/hashicorp/terraform-plugin-framework/path"
13
15
"github.com/hashicorp/terraform-plugin-framework/resource"
14
16
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
15
17
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
16
18
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
19
+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
17
20
18
21
"github.com/segmentio/public-api-sdk-go/api"
19
22
)
@@ -91,12 +94,27 @@ func (r *destinationSubscriptionResource) Schema(_ context.Context, _ resource.S
91
94
Description : `The customer settings for action fields. Only settings included in the configuration will be managed by Terraform.` ,
92
95
CustomType : jsontypes.NormalizedType {},
93
96
},
97
+ "reverse_etl_schedule" : schema.SingleNestedAttribute {
98
+ Optional : true ,
99
+ Description : "(Reverse ETL only) The schedule for the subscription being attached to ReverseETL model." ,
100
+ Attributes : map [string ]schema.Attribute {
101
+ "strategy" : schema.StringAttribute {
102
+ Required : true ,
103
+ Description : "Strategy supports three modes: PERIODIC, SPECIFIC_DAYS, or MANUAL." ,
104
+ },
105
+ "config" : schema.StringAttribute {
106
+ Optional : true ,
107
+ Description : "Configures the schedule for the subscription." ,
108
+ CustomType : jsontypes.NormalizedType {},
109
+ },
110
+ },
111
+ },
94
112
},
95
113
}
96
114
}
97
115
98
116
func (r * destinationSubscriptionResource ) Create (ctx context.Context , req resource.CreateRequest , resp * resource.CreateResponse ) {
99
- var plan models.DestinationSubscriptionState
117
+ var plan models.DestinationSubscriptionPlan
100
118
diags := req .Plan .Get (ctx , & plan )
101
119
resp .Diagnostics .Append (diags ... )
102
120
if resp .Diagnostics .HasError () {
@@ -110,6 +128,15 @@ func (r *destinationSubscriptionResource) Create(ctx context.Context, req resour
110
128
return
111
129
}
112
130
131
+ if ! plan .ModelID .IsNull () && ! plan .ModelID .IsUnknown () && (plan .ReverseETLSchedule .IsNull () || plan .ReverseETLSchedule .IsUnknown ()) {
132
+ resp .Diagnostics .AddError (
133
+ "Reverse ETL model ID provided without reverse ETL schedule" ,
134
+ "Reverse ETL model ID must be provided with a reverse ETL schedule" ,
135
+ )
136
+
137
+ return
138
+ }
139
+
113
140
out , body , err := r .client .DestinationsAPI .CreateDestinationSubscription (r .authContext , plan .DestinationID .ValueString ()).CreateDestinationSubscriptionAlphaInput (api.CreateDestinationSubscriptionAlphaInput {
114
141
Name : plan .Name .ValueString (),
115
142
ActionId : plan .ActionID .ValueString (),
@@ -130,9 +157,38 @@ func (r *destinationSubscriptionResource) Create(ctx context.Context, req resour
130
157
return
131
158
}
132
159
133
- destinationSubscription := out .Data .GetDestinationSubscription ()
160
+ resp .State .SetAttribute (ctx , path .Root ("id" ), out .Data .DestinationSubscription .Id )
161
+ resp .State .SetAttribute (ctx , path .Root ("destination_id" ), out .Data .DestinationSubscription .DestinationId )
162
+
163
+ reverseETLSchedule , diags := getSchedule (ctx , plan .ReverseETLSchedule )
164
+ if diags .HasError () {
165
+ resp .Diagnostics .Append (diags ... )
166
+ return
167
+ }
168
+
169
+ updateOut , body , err := r .client .DestinationsAPI .UpdateSubscriptionForDestination (r .authContext , plan .DestinationID .ValueString (), out .Data .DestinationSubscription .Id ).UpdateSubscriptionForDestinationAlphaInput (api.UpdateSubscriptionForDestinationAlphaInput {
170
+ Input : api.DestinationSubscriptionUpdateInput {
171
+ Name : plan .Name .ValueStringPointer (),
172
+ Trigger : plan .Trigger .ValueStringPointer (),
173
+ Enabled : plan .Enabled .ValueBoolPointer (),
174
+ Settings : settings ,
175
+ ReverseETLModelId : plan .ModelID .ValueStringPointer (),
176
+ ReverseETLSchedule : reverseETLSchedule ,
177
+ },
178
+ }).Execute ()
179
+ if body != nil {
180
+ defer body .Body .Close ()
181
+ }
182
+ if err != nil {
183
+ resp .Diagnostics .AddError (
184
+ "Unable to update Destination subscription" ,
185
+ getError (err , body ),
186
+ )
187
+
188
+ return
189
+ }
134
190
135
- resp . State . SetAttribute ( ctx , path . Root ( "id" ), destinationSubscription . Id )
191
+ destinationSubscription := updateOut . Data . Subscription
136
192
137
193
var state models.DestinationSubscriptionState
138
194
err = state .Fill (destinationSubscription )
@@ -203,7 +259,7 @@ func (r *destinationSubscriptionResource) Read(ctx context.Context, req resource
203
259
}
204
260
205
261
func (r * destinationSubscriptionResource ) Update (ctx context.Context , req resource.UpdateRequest , resp * resource.UpdateResponse ) {
206
- var plan models.DestinationSubscriptionState
262
+ var plan models.DestinationSubscriptionPlan
207
263
diags := req .Plan .Get (ctx , & plan )
208
264
resp .Diagnostics .Append (diags ... )
209
265
if resp .Diagnostics .HasError () {
@@ -224,12 +280,29 @@ func (r *destinationSubscriptionResource) Update(ctx context.Context, req resour
224
280
return
225
281
}
226
282
283
+ if ! plan .ModelID .IsNull () && ! plan .ModelID .IsUnknown () && (plan .ReverseETLSchedule .IsNull () || plan .ReverseETLSchedule .IsUnknown ()) {
284
+ resp .Diagnostics .AddError (
285
+ "Reverse ETL model ID provided without reverse ETL schedule" ,
286
+ "Reverse ETL model ID must be provided with a reverse ETL schedule" ,
287
+ )
288
+
289
+ return
290
+ }
291
+
292
+ reverseETLSchedule , diags := getSchedule (ctx , plan .ReverseETLSchedule )
293
+ if diags .HasError () {
294
+ resp .Diagnostics .Append (diags ... )
295
+ return
296
+ }
297
+
227
298
out , body , err := r .client .DestinationsAPI .UpdateSubscriptionForDestination (r .authContext , state .DestinationID .ValueString (), state .ID .ValueString ()).UpdateSubscriptionForDestinationAlphaInput (api.UpdateSubscriptionForDestinationAlphaInput {
228
299
Input : api.DestinationSubscriptionUpdateInput {
229
- Name : plan .Name .ValueStringPointer (),
230
- Trigger : plan .Trigger .ValueStringPointer (),
231
- Enabled : plan .Enabled .ValueBoolPointer (),
232
- Settings : settings ,
300
+ Name : plan .Name .ValueStringPointer (),
301
+ Trigger : plan .Trigger .ValueStringPointer (),
302
+ Enabled : plan .Enabled .ValueBoolPointer (),
303
+ Settings : settings ,
304
+ ReverseETLModelId : plan .ModelID .ValueStringPointer (),
305
+ ReverseETLSchedule : reverseETLSchedule ,
233
306
},
234
307
}).Execute ()
235
308
if body != nil {
@@ -320,3 +393,115 @@ func (r *destinationSubscriptionResource) Configure(_ context.Context, req resou
320
393
r .client = config .client
321
394
r .authContext = config .authContext
322
395
}
396
+
397
+ func getSchedule (ctx context.Context , planSchedule basetypes.ObjectValue ) (* api.ReverseEtlScheduleDefinition , diag.Diagnostics ) {
398
+ var reverseETLSchedule * api.ReverseEtlScheduleDefinition
399
+ var diags diag.Diagnostics
400
+ if ! planSchedule .IsNull () && ! planSchedule .IsUnknown () {
401
+ reverseETLSchedule = & api.ReverseEtlScheduleDefinition {}
402
+
403
+ wrappedReverseETLModelScheduleStrategy , err := planSchedule .Attributes ()["strategy" ].ToTerraformValue (ctx )
404
+ if err != nil {
405
+ diags .AddError (
406
+ "Unable to decode reverse ETL schedule strategy" ,
407
+ err .Error (),
408
+ )
409
+
410
+ return nil , diags
411
+ }
412
+
413
+ var reverseETLModelScheduleStrategy string
414
+ err = wrappedReverseETLModelScheduleStrategy .As (& reverseETLModelScheduleStrategy )
415
+ if err != nil {
416
+ diags .AddError (
417
+ "Unable to decode reverse ETL schedule strategy" ,
418
+ err .Error (),
419
+ )
420
+
421
+ return nil , diags
422
+ }
423
+
424
+ reverseETLSchedule .Strategy = reverseETLModelScheduleStrategy
425
+
426
+ wrappedReverseETLModelScheduleConfig , err := planSchedule .Attributes ()["config" ].ToTerraformValue (ctx )
427
+ if err != nil {
428
+ diags .AddError (
429
+ "Unable to decode reverse ETL schedule config" ,
430
+ err .Error (),
431
+ )
432
+
433
+ return nil , diags
434
+ }
435
+
436
+ if ! wrappedReverseETLModelScheduleConfig .IsNull () && wrappedReverseETLModelScheduleConfig .IsKnown () {
437
+ if reverseETLSchedule .Strategy == "PERIODIC" {
438
+ reverseETLModelScheduleConfig := api.ReverseEtlPeriodicScheduleConfig {}
439
+ var config string
440
+ err = wrappedReverseETLModelScheduleConfig .As (& config )
441
+ if err != nil {
442
+ diags .AddError (
443
+ "Unable to decode reverse ETL schedule config" ,
444
+ err .Error (),
445
+ )
446
+
447
+ return nil , diags
448
+ }
449
+
450
+ err = json .Unmarshal ([]byte (config ), & reverseETLModelScheduleConfig )
451
+ if err != nil {
452
+ diags .AddError (
453
+ "Unable to decode reverse ETL schedule config" ,
454
+ err .Error (),
455
+ )
456
+
457
+ return nil , diags
458
+ }
459
+
460
+ reverseETLSchedule .Config = * api .NewNullableConfig (& api.Config {
461
+ ReverseEtlPeriodicScheduleConfig : & reverseETLModelScheduleConfig ,
462
+ })
463
+ } else if reverseETLSchedule .Strategy == "SPECIFIC_DAYS" {
464
+ reverseETLModelScheduleConfig := api.ReverseEtlSpecificTimeScheduleConfig {}
465
+ var config string
466
+ err = wrappedReverseETLModelScheduleConfig .As (& config )
467
+ if err != nil {
468
+ diags .AddError (
469
+ "Unable to decode reverse ETL schedule config" ,
470
+ err .Error (),
471
+ )
472
+
473
+ return nil , diags
474
+ }
475
+
476
+ err = json .Unmarshal ([]byte (config ), & reverseETLModelScheduleConfig )
477
+ if err != nil {
478
+ diags .AddError (
479
+ "Unable to decode reverse ETL schedule config" ,
480
+ err .Error (),
481
+ )
482
+
483
+ return nil , diags
484
+ }
485
+
486
+ reverseETLSchedule .Config = * api .NewNullableConfig (& api.Config {
487
+ ReverseEtlSpecificTimeScheduleConfig : & reverseETLModelScheduleConfig ,
488
+ })
489
+ } else if reverseETLSchedule .Strategy == "MANUAL" {
490
+ diags .AddError (
491
+ "Manual reverse ETL schedule strategy does not require a config" ,
492
+ "Manual reverse ETL schedule strategy does not require a config" ,
493
+ )
494
+ reverseETLSchedule .Config = * api .NewNullableConfig (nil )
495
+ } else {
496
+ diags .AddError (
497
+ "Unsupported reverse ETL schedule strategy" ,
498
+ fmt .Sprintf ("Strategy %q is not supported" , reverseETLSchedule .Strategy ),
499
+ )
500
+
501
+ return nil , diags
502
+ }
503
+ }
504
+ }
505
+
506
+ return reverseETLSchedule , diags
507
+ }
0 commit comments