|
7 | 7 | "context"
|
8 | 8 | "encoding/json"
|
9 | 9 | "fmt"
|
| 10 | + "net" |
10 | 11 | "net/http"
|
11 | 12 | "reflect"
|
12 | 13 | "strings"
|
@@ -135,6 +136,9 @@ func (r *SettingsResource) Create(ctx context.Context, req resource.CreateReques
|
135 | 136 | if !data.Database.IsNull() {
|
136 | 137 | resp.Diagnostics.Append(updateDatabaseConfig(ctx, &data, r.client)...)
|
137 | 138 | }
|
| 139 | + if !data.Network.IsNull() { |
| 140 | + resp.Diagnostics.Append(updateNetworkConfig(ctx, &data, r.client)...) |
| 141 | + } |
138 | 142 | if !data.Api.IsNull() {
|
139 | 143 | resp.Diagnostics.Append(updateApiConfig(ctx, &data, r.client)...)
|
140 | 144 | }
|
@@ -170,6 +174,9 @@ func (r *SettingsResource) Read(ctx context.Context, req resource.ReadRequest, r
|
170 | 174 | if !data.Database.IsNull() {
|
171 | 175 | resp.Diagnostics.Append(readDatabaseConfig(ctx, &data, r.client)...)
|
172 | 176 | }
|
| 177 | + if !data.Network.IsNull() { |
| 178 | + resp.Diagnostics.Append(readNetworkConfig(ctx, &data, r.client)...) |
| 179 | + } |
173 | 180 | if !data.Api.IsNull() {
|
174 | 181 | resp.Diagnostics.Append(readApiConfig(ctx, &data, r.client)...)
|
175 | 182 | }
|
@@ -200,6 +207,9 @@ func (r *SettingsResource) Update(ctx context.Context, req resource.UpdateReques
|
200 | 207 | if !data.Database.IsNull() {
|
201 | 208 | resp.Diagnostics.Append(updateDatabaseConfig(ctx, &data, r.client)...)
|
202 | 209 | }
|
| 210 | + if !data.Network.IsNull() { |
| 211 | + resp.Diagnostics.Append(updateNetworkConfig(ctx, &data, r.client)...) |
| 212 | + } |
203 | 213 | if !data.Api.IsNull() {
|
204 | 214 | resp.Diagnostics.Append(updateApiConfig(ctx, &data, r.client)...)
|
205 | 215 | }
|
@@ -233,6 +243,7 @@ func (r *SettingsResource) ImportState(ctx context.Context, req resource.ImportS
|
233 | 243 | // Read all configs from API when importing so it's easier to pick
|
234 | 244 | // individual fields to manage through TF.
|
235 | 245 | resp.Diagnostics.Append(readDatabaseConfig(ctx, &data, r.client)...)
|
| 246 | + resp.Diagnostics.Append(readNetworkConfig(ctx, &data, r.client)...) |
236 | 247 | resp.Diagnostics.Append(readApiConfig(ctx, &data, r.client)...)
|
237 | 248 | resp.Diagnostics.Append(readAuthConfig(ctx, &data, r.client)...)
|
238 | 249 |
|
@@ -417,3 +428,82 @@ func copyConfig(source any, target map[string]interface{}) {
|
417 | 428 | }
|
418 | 429 | }
|
419 | 430 | }
|
| 431 | + |
| 432 | +type NetworkConfig struct { |
| 433 | + Restrictions []string `json:"restrictions,omitempty"` |
| 434 | +} |
| 435 | + |
| 436 | +func readNetworkConfig(ctx context.Context, state *SettingsResourceModel, client *api.ClientWithResponses) diag.Diagnostics { |
| 437 | + httpResp, err := client.GetNetworkRestrictionsWithResponse(ctx, state.Id.ValueString()) |
| 438 | + if err != nil { |
| 439 | + msg := fmt.Sprintf("Unable to read network settings, got error: %s", err) |
| 440 | + return diag.Diagnostics{diag.NewErrorDiagnostic("Client Error", msg)} |
| 441 | + } |
| 442 | + // Deleted project is an orphan resource, not returning error so it can be destroyed. |
| 443 | + switch httpResp.StatusCode() { |
| 444 | + case http.StatusNotFound, http.StatusNotAcceptable: |
| 445 | + return nil |
| 446 | + } |
| 447 | + if httpResp.JSON200 == nil { |
| 448 | + msg := fmt.Sprintf("Unable to read network settings, got status %d: %s", httpResp.StatusCode(), httpResp.Body) |
| 449 | + return diag.Diagnostics{diag.NewErrorDiagnostic("Client Error", msg)} |
| 450 | + } |
| 451 | + |
| 452 | + var network NetworkConfig |
| 453 | + if v4 := httpResp.JSON200.Config.DbAllowedCidrs; v4 != nil { |
| 454 | + network.Restrictions = append(network.Restrictions, *v4...) |
| 455 | + } |
| 456 | + if v6 := httpResp.JSON200.Config.DbAllowedCidrsV6; v6 != nil { |
| 457 | + network.Restrictions = append(network.Restrictions, *v6...) |
| 458 | + } |
| 459 | + |
| 460 | + if state.Network, err = parseConfig(state.Network, network); err != nil { |
| 461 | + msg := fmt.Sprintf("Unable to read network settings, got error: %s", err) |
| 462 | + return diag.Diagnostics{diag.NewErrorDiagnostic("Client Error", msg)} |
| 463 | + } |
| 464 | + return nil |
| 465 | +} |
| 466 | + |
| 467 | +func updateNetworkConfig(ctx context.Context, plan *SettingsResourceModel, client *api.ClientWithResponses) diag.Diagnostics { |
| 468 | + var network NetworkConfig |
| 469 | + if diags := plan.Network.Unmarshal(&network); diags.HasError() { |
| 470 | + return diags |
| 471 | + } |
| 472 | + |
| 473 | + body := api.ApplyNetworkRestrictionsJSONRequestBody{ |
| 474 | + DbAllowedCidrs: &[]string{}, |
| 475 | + DbAllowedCidrsV6: &[]string{}, |
| 476 | + } |
| 477 | + for _, cidr := range network.Restrictions { |
| 478 | + ip, _, err := net.ParseCIDR(cidr) |
| 479 | + if err != nil { |
| 480 | + msg := fmt.Sprintf("Invalid CIDR provided for network restrictions: %s", err) |
| 481 | + return diag.Diagnostics{diag.NewErrorDiagnostic("Client Error", msg)} |
| 482 | + } |
| 483 | + if ip.IsPrivate() { |
| 484 | + msg := fmt.Sprintf("Private IP provided for network restrictions: %s", cidr) |
| 485 | + return diag.Diagnostics{diag.NewErrorDiagnostic("Client Error", msg)} |
| 486 | + } |
| 487 | + if ip.To4() != nil { |
| 488 | + *body.DbAllowedCidrs = append(*body.DbAllowedCidrs, cidr) |
| 489 | + } else { |
| 490 | + *body.DbAllowedCidrsV6 = append(*body.DbAllowedCidrsV6, cidr) |
| 491 | + } |
| 492 | + } |
| 493 | + |
| 494 | + httpResp, err := client.ApplyNetworkRestrictionsWithResponse(ctx, plan.ProjectRef.ValueString(), body) |
| 495 | + if err != nil { |
| 496 | + msg := fmt.Sprintf("Unable to update network settings, got error: %s", err) |
| 497 | + return diag.Diagnostics{diag.NewErrorDiagnostic("Client Error", msg)} |
| 498 | + } |
| 499 | + if httpResp.JSON201 == nil { |
| 500 | + msg := fmt.Sprintf("Unable to update network settings, got status %d: %s", httpResp.StatusCode(), httpResp.Body) |
| 501 | + return diag.Diagnostics{diag.NewErrorDiagnostic("Client Error", msg)} |
| 502 | + } |
| 503 | + |
| 504 | + if plan.Network, err = parseConfig(plan.Network, network); err != nil { |
| 505 | + msg := fmt.Sprintf("Unable to update network settings, got error: %s", err) |
| 506 | + return diag.Diagnostics{diag.NewErrorDiagnostic("Client Error", msg)} |
| 507 | + } |
| 508 | + return nil |
| 509 | +} |
0 commit comments