9
9
"io"
10
10
"net/http"
11
11
"strconv"
12
+ "time"
12
13
13
14
"github.com/cloudflare/cloudflare-go/v5"
14
15
"github.com/cloudflare/cloudflare-go/v5/option"
@@ -97,6 +98,12 @@ func (r *ListItemResource) Create(ctx context.Context, req resource.CreateReques
97
98
return
98
99
}
99
100
101
+ err = pollBulkOperation (ctx , data .AccountID .ValueString (), createEnv .Result .OperationID .ValueString (), r .client )
102
+ if err != nil {
103
+ resp .Diagnostics .AddError ("list item bulk operation failed" , err .Error ())
104
+ return
105
+ }
106
+
100
107
searchTerm := getSearchTerm (data )
101
108
findItemRes := new (http.Response )
102
109
_ , err = r .client .Rules .Lists .Items .List (
@@ -162,20 +169,23 @@ func (r *ListItemResource) Update(ctx context.Context, req resource.UpdateReques
162
169
return
163
170
}
164
171
165
- dataBytes , err := data .MarshalJSONForUpdate ( * state )
172
+ dataBytes , err := data .MarshalJSON ( )
166
173
if err != nil {
167
174
resp .Diagnostics .AddError ("failed to serialize http request" , err .Error ())
168
175
return
169
176
}
177
+
178
+ wrappedBytes := data .MarshalSingleToCollectionJSON (dataBytes )
179
+
170
180
res := new (http.Response )
171
- env := ListItemResultEnvelope {* data }
172
- _ , err = r .client .Rules .Lists .Items .Update (
181
+ createEnv := ListItemResultEnvelope {* data }
182
+ _ , err = r .client .Rules .Lists .Items .New (
173
183
ctx ,
174
184
data .ListID .ValueString (),
175
- rules.ListItemUpdateParams {
185
+ rules.ListItemNewParams {
176
186
AccountID : cloudflare .F (data .AccountID .ValueString ()),
177
187
},
178
- option .WithRequestBody ("application/json" , dataBytes ),
188
+ option .WithRequestBody ("application/json" , wrappedBytes ),
179
189
option .WithResponseBodyInto (& res ),
180
190
option .WithMiddleware (logging .Middleware (ctx )),
181
191
)
@@ -184,11 +194,62 @@ func (r *ListItemResource) Update(ctx context.Context, req resource.UpdateReques
184
194
return
185
195
}
186
196
bytes , _ := io .ReadAll (res .Body )
187
- err = apijson .UnmarshalComputed (bytes , & env )
197
+
198
+ err = apijson .UnmarshalComputed (bytes , & createEnv )
188
199
if err != nil {
189
200
resp .Diagnostics .AddError ("failed to deserialize http request" , err .Error ())
190
201
return
191
202
}
203
+
204
+ err = pollBulkOperation (ctx , data .AccountID .ValueString (), createEnv .Result .OperationID .ValueString (), r .client )
205
+ if err != nil {
206
+ resp .Diagnostics .AddError ("list item bulk operation failed" , err .Error ())
207
+ return
208
+ }
209
+
210
+ searchTerm := getSearchTerm (data )
211
+ findItemRes := new (http.Response )
212
+ _ , err = r .client .Rules .Lists .Items .List (
213
+ ctx ,
214
+ data .ListID .ValueString (),
215
+ rules.ListItemListParams {
216
+ AccountID : cloudflare .F (data .AccountID .ValueString ()),
217
+ Search : cloudflare .F (searchTerm ),
218
+ },
219
+ option .WithResponseBodyInto (& findItemRes ),
220
+ option .WithMiddleware (logging .Middleware (ctx )),
221
+ )
222
+ if err != nil {
223
+ resp .Diagnostics .AddError ("failed to fetch individual list item" , err .Error ())
224
+ return
225
+ }
226
+ findListItem , _ := io .ReadAll (findItemRes .Body )
227
+ itemID := gjson .Get (string (findListItem ), "result.0.id" )
228
+ data .ID = types .StringValue (itemID .String ())
229
+
230
+ env := ListItemResultEnvelope {* data }
231
+ listItemRes := new (http.Response )
232
+ _ , err = r .client .Rules .Lists .Items .Get (
233
+ ctx ,
234
+ data .ListID .ValueString (),
235
+ data .ID .ValueString (),
236
+ rules.ListItemGetParams {
237
+ AccountID : cloudflare .F (data .AccountID .ValueString ()),
238
+ },
239
+ option .WithResponseBodyInto (& listItemRes ),
240
+ option .WithMiddleware (logging .Middleware (ctx )),
241
+ )
242
+ if err != nil {
243
+ resp .Diagnostics .AddError ("failed to fetch individual list item" , err .Error ())
244
+ return
245
+ }
246
+ listItem , _ := io .ReadAll (listItemRes .Body )
247
+ err = apijson .UnmarshalComputed (listItem , & env )
248
+ if err != nil {
249
+ resp .Diagnostics .AddError ("failed to deserialize http request" , err .Error ())
250
+ return
251
+ }
252
+
192
253
data = & env .Result
193
254
194
255
resp .Diagnostics .Append (resp .State .Set (ctx , & data )... )
@@ -269,6 +330,37 @@ func (r *ListItemResource) ModifyPlan(_ context.Context, _ resource.ModifyPlanRe
269
330
270
331
}
271
332
333
+ func pollBulkOperation (ctx context.Context , accountID , operationID string , client * cloudflare.Client ) error {
334
+ backoff := 1 * time .Second
335
+ maxBackoff := 30 * time .Second
336
+
337
+ for {
338
+ bulkOperation , err := client .Rules .Lists .BulkOperations .Get (
339
+ ctx ,
340
+ operationID ,
341
+ rules.ListBulkOperationGetParams {
342
+ AccountID : cloudflare .F (accountID ),
343
+ },
344
+ option .WithMiddleware (logging .Middleware (ctx )),
345
+ )
346
+ if err != nil {
347
+ return err
348
+ }
349
+ switch bulkOperation .Status {
350
+ case rules .ListBulkOperationGetResponseStatusCompleted :
351
+ return nil
352
+ case rules .ListBulkOperationGetResponseStatusFailed :
353
+ return fmt .Errorf ("failed to create list item: %s" , bulkOperation .Error )
354
+ default :
355
+ time .Sleep (backoff )
356
+ backoff *= 2
357
+ if backoff > maxBackoff {
358
+ backoff = maxBackoff
359
+ }
360
+ }
361
+ }
362
+ }
363
+
272
364
type bodyDeletePayload struct {
273
365
Items []bodyDeleteItems `json:"items"`
274
366
}
0 commit comments