|
9 | 9 | "strings" |
10 | 10 |
|
11 | 11 | jsonpatch "github.com/evanphx/json-patch" |
| 12 | + "github.com/hashicorp/terraform-plugin-framework-validators/boolvalidator" |
12 | 13 | "github.com/hashicorp/terraform-plugin-framework-validators/dynamicvalidator" |
13 | 14 | "github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator" |
14 | 15 | "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" |
@@ -105,6 +106,7 @@ type resourceData struct { |
105 | 106 | type bodyPatchData struct { |
106 | 107 | Path types.String `tfsdk:"path"` |
107 | 108 | RawJSON types.String `tfsdk:"raw_json"` |
| 109 | + Removed types.Bool `tfsdk:"removed"` |
108 | 110 | } |
109 | 111 |
|
110 | 112 | type pollData struct { |
@@ -422,9 +424,25 @@ func (r *Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp |
422 | 424 | Required: true, |
423 | 425 | }, |
424 | 426 | "raw_json": schema.StringAttribute{ |
425 | | - Description: "The raw json used as the patch value. It can contain `$(body.x.y.z)` parameter that reference property from the `state.output`.", |
426 | | - MarkdownDescription: "The raw json used as the patch value. It can contain `$(body.x.y.z)` parameter that reference property from the `state.output`.", |
427 | | - Required: true, |
| 427 | + MarkdownDescription: "The raw json used as the patch value. It can contain `$(body.x.y.z)` parameter that reference property from the `state.output`. Exactly one of `raw_json` and `removed` shall be specified.", |
| 428 | + Optional: true, |
| 429 | + Validators: []validator.String{ |
| 430 | + stringvalidator.ExactlyOneOf( |
| 431 | + path.MatchRelative().AtParent().AtName("raw_json"), |
| 432 | + path.MatchRelative().AtParent().AtName("removed"), |
| 433 | + ), |
| 434 | + }, |
| 435 | + }, |
| 436 | + "removed": schema.BoolAttribute{ |
| 437 | + MarkdownDescription: "Remove the value specified by `path` from the update body. Exactly one of `raw_json` and `removed` shall be specified", |
| 438 | + Optional: true, |
| 439 | + Validators: []validator.Bool{ |
| 440 | + boolvalidator.Equals(true), |
| 441 | + boolvalidator.ExactlyOneOf( |
| 442 | + path.MatchRelative().AtParent().AtName("raw_json"), |
| 443 | + path.MatchRelative().AtParent().AtName("removed"), |
| 444 | + ), |
| 445 | + }, |
428 | 446 | }, |
429 | 447 | }, |
430 | 448 | }, |
@@ -1356,22 +1374,34 @@ func (r Resource) Update(ctx context.Context, req resource.UpdateRequest, resp * |
1356 | 1374 | if len(patches) != 0 { |
1357 | 1375 | planBodyStr := string(planBody) |
1358 | 1376 | for i, patch := range patches { |
1359 | | - pv, err := exparam.ExpandBody(patch.RawJSON.ValueString(), stateOutput) |
1360 | | - if err != nil { |
1361 | | - resp.Diagnostics.AddError( |
1362 | | - fmt.Sprintf("Failed to expand the %d-th patch for expression params", i), |
1363 | | - err.Error(), |
1364 | | - ) |
1365 | | - return |
1366 | | - } |
| 1377 | + switch { |
| 1378 | + case !patch.Removed.IsNull(): |
| 1379 | + planBodyStr, err = sjson.Delete(planBodyStr, patch.Path.ValueString()) |
| 1380 | + if err != nil { |
| 1381 | + resp.Diagnostics.AddError( |
| 1382 | + fmt.Sprintf("Failed to delete json for the %d-th patch at path %q", i, patch.Path.ValueString()), |
| 1383 | + err.Error(), |
| 1384 | + ) |
| 1385 | + return |
| 1386 | + } |
| 1387 | + case !patch.RawJSON.IsNull(): |
| 1388 | + pv, err := exparam.ExpandBody(patch.RawJSON.ValueString(), stateOutput) |
| 1389 | + if err != nil { |
| 1390 | + resp.Diagnostics.AddError( |
| 1391 | + fmt.Sprintf("Failed to expand the %d-th patch for expression params", i), |
| 1392 | + err.Error(), |
| 1393 | + ) |
| 1394 | + return |
| 1395 | + } |
1367 | 1396 |
|
1368 | | - planBodyStr, err = sjson.SetRaw(planBodyStr, patch.Path.ValueString(), pv) |
1369 | | - if err != nil { |
1370 | | - resp.Diagnostics.AddError( |
1371 | | - fmt.Sprintf("Failed to set json for the %d-th patch for expression params", i), |
1372 | | - err.Error(), |
1373 | | - ) |
1374 | | - return |
| 1397 | + planBodyStr, err = sjson.SetRaw(planBodyStr, patch.Path.ValueString(), pv) |
| 1398 | + if err != nil { |
| 1399 | + resp.Diagnostics.AddError( |
| 1400 | + fmt.Sprintf("Failed to set json for the %d-th patch with %q", i, pv), |
| 1401 | + err.Error(), |
| 1402 | + ) |
| 1403 | + return |
| 1404 | + } |
1375 | 1405 | } |
1376 | 1406 | } |
1377 | 1407 | planBody = []byte(planBodyStr) |
|
0 commit comments