Skip to content

Commit 8f79021

Browse files
ybrybr-sanofideanhuynh
authored
fix: handle profiles warehouse schemaName (#204)
Co-authored-by: Yohann Brédoux <[email protected]> Co-authored-by: Dean Huynh <[email protected]>
1 parent 3d534ac commit 8f79021

File tree

2 files changed

+456
-8
lines changed

2 files changed

+456
-8
lines changed

internal/provider/profiles_warehouse_resource.go

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
1616
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
1717
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
18+
"github.com/hashicorp/terraform-plugin-framework/types"
1819

1920
"github.com/segmentio/public-api-sdk-go/api"
2021
)
@@ -144,10 +145,10 @@ func (r *profilesWarehouseResource) Create(ctx context.Context, req resource.Cre
144145
return
145146
}
146147

147-
// This is to satisfy terraform requirements that the returned fields must match the input ones because new settings can be generated in the response
148+
// This is to satisfy terraform requirements that the returned fields must match the input ones because new settings can be generated in the response.
148149
state.Settings = plan.Settings
149150

150-
// Set state to fully populated data
151+
// Set state to fully populated data.
151152
diags = resp.State.Set(ctx, state)
152153
resp.Diagnostics.Append(diags...)
153154
if resp.Diagnostics.HasError() {
@@ -238,11 +239,30 @@ func (r *profilesWarehouseResource) Update(ctx context.Context, req resource.Upd
238239
return
239240
}
240241

242+
if (plan.SchemaName.IsNull() || plan.SchemaName.IsUnknown()) && !state.SchemaName.IsNull() {
243+
resp.Diagnostics.AddError(
244+
fmt.Sprintf("Unable to update Profiles Warehouse (ID: %s)", plan.ID.ValueString()),
245+
"Cannot unset schema name",
246+
)
247+
248+
return
249+
}
250+
251+
// Only send schemaName to API if it differs from the remote state.
252+
// This prevents API failures when the schema name already exists in the warehouse.
253+
// The Segment API fails if we send a schemaName that matches the current configuration.
254+
// even though it should be a no-op. This handles all cases:
255+
// 1. Both null/undefined: Equal() returns true, schemaName stays nil (not sent).
256+
// 2. Both have same value: Equal() returns true, schemaName stays nil (not sent).
257+
// 3. One null, other has value: Equal() returns false, schemaName gets the plan value (sent).
258+
// 4. Both have different values: Equal() returns false, schemaName gets the plan value (sent).
259+
schemaName := determineSchemaNameForUpdate(plan.SchemaName, state.SchemaName)
260+
241261
out, body, err := r.client.ProfilesSyncAPI.UpdateProfilesWarehouseForSpaceWarehouse(r.authContext, state.SpaceID.ValueString(), state.ID.ValueString()).UpdateProfilesWarehouseForSpaceWarehouseAlphaInput(api.UpdateProfilesWarehouseForSpaceWarehouseAlphaInput{
242262
Enabled: plan.Enabled.ValueBoolPointer(),
243263
Settings: settings,
244264
Name: plan.Name.ValueStringPointer(),
245-
SchemaName: plan.SchemaName.ValueStringPointer(),
265+
SchemaName: schemaName,
246266
}).Execute()
247267
if body != nil {
248268
defer body.Body.Close()
@@ -268,7 +288,7 @@ func (r *profilesWarehouseResource) Update(ctx context.Context, req resource.Upd
268288
return
269289
}
270290

271-
// This is to satisfy terraform requirements that the returned fields must match the input ones because new settings can be generated in the response
291+
// This is to satisfy terraform requirements that the returned fields must match the input ones because new settings can be generated in the response.
272292
state.Settings = plan.Settings
273293

274294
diags = resp.State.Set(ctx, &state)
@@ -362,3 +382,27 @@ func findProfileWarehouse(authContext context.Context, client *api.APIClient, id
362382

363383
return nil, nil
364384
}
385+
386+
// determineSchemaNameForUpdate determines whether schemaName should be sent to the API
387+
// based on comparing the plan and state values. This prevents API failures when the
388+
// schema name already exists in the warehouse configuration.
389+
//
390+
// The function returns nil (not sent to API) when:
391+
// - Plan value is unknown (should not send unknown values to API).
392+
// - Plan and state values are equal (no change needed).
393+
//
394+
// The function returns a pointer to the plan value when:
395+
// - Plan and state values are different (legitimate change).
396+
func determineSchemaNameForUpdate(planSchemaName, stateSchemaName types.String) *string {
397+
// Don't send schemaName to API if plan value is unknown.
398+
if planSchemaName.IsUnknown() {
399+
return nil
400+
}
401+
402+
// Only send schemaName to API if it differs from the remote state.
403+
if !planSchemaName.Equal(stateSchemaName) {
404+
return planSchemaName.ValueStringPointer()
405+
}
406+
407+
return nil
408+
}

0 commit comments

Comments
 (0)