in internal/services/azapi_data_plane_resource.go [376:469]
func (r *DataPlaneResource) CreateUpdate(ctx context.Context, plan tfsdk.Plan, state *tfsdk.State, diagnostics *diag.Diagnostics) {
var model DataPlaneResourceModel
if diagnostics.Append(plan.Get(ctx, &model)...); diagnostics.HasError() {
return
}
id, err := parse.NewDataPlaneResourceId(model.Name.ValueString(), model.ParentID.ValueString(), model.Type.ValueString())
if err != nil {
diagnostics.AddError("Invalid configuration", err.Error())
return
}
ctx = tflog.SetField(ctx, "resource_id", id.ID())
isNewResource := state == nil || state.Raw.IsNull()
var timeout time.Duration
var diags diag.Diagnostics
if isNewResource {
timeout, diags = model.Timeouts.Create(ctx, 30*time.Minute)
if diagnostics.Append(diags...); diagnostics.HasError() {
return
}
} else {
timeout, diags = model.Timeouts.Update(ctx, 30*time.Minute)
if diagnostics.Append(diags...); diagnostics.HasError() {
return
}
}
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
// Ensure the context deadline has been set before calling ConfigureClientWithCustomRetry().
client := r.ProviderData.DataPlaneClient.ConfigureClientWithCustomRetry(ctx, model.Retry, false)
if isNewResource {
// check if the resource already exists using the non-retry client to avoid issue where user specifies
// a FooResourceNotFound error as a retryable error
_, err = r.ProviderData.DataPlaneClient.Get(ctx, id, clients.NewRequestOptions(AsMapOfString(model.ReadHeaders), AsMapOfLists(model.ReadQueryParameters)))
if err == nil {
diagnostics.AddError("Resource already exists", tf.ImportAsExistsError("azapi_data_plane_resource", id.ID()).Error())
return
}
if !utils.ResponseErrorWasNotFound(err) {
diagnostics.AddError("Failed to retrieve resource", fmt.Errorf("checking for presence of existing %s: %+v", id, err).Error())
return
}
}
body := make(map[string]interface{})
if err := unmarshalBody(model.Body, &body); err != nil {
diagnostics.AddError("Invalid body", fmt.Sprintf(`The argument "body" is invalid: %s`, err.Error()))
return
}
lockIds := AsStringList(model.Locks)
slices.Sort(lockIds)
for _, lockId := range lockIds {
locks.ByID(lockId)
defer locks.UnlockByID(lockId)
}
_, err = client.CreateOrUpdateThenPoll(ctx, id, body, clients.NewRequestOptions(AsMapOfString(model.CreateHeaders), AsMapOfLists(model.CreateQueryParameters)))
if err != nil {
diagnostics.AddError("Failed to create/update resource", fmt.Errorf("creating/updating %q: %+v", id, err).Error())
return
}
// Create a new retry client to handle specific case of transient 403/404 after resource creation
// If a read after create retry is not specified, use the default.
clientGetAfterPut := r.ProviderData.DataPlaneClient.ConfigureClientWithCustomRetry(ctx, model.Retry, true)
responseBody, err := clientGetAfterPut.Get(ctx, id, clients.NewRequestOptions(AsMapOfString(model.ReadHeaders), AsMapOfLists(model.ReadQueryParameters)))
if err != nil {
if utils.ResponseErrorWasNotFound(err) {
tflog.Info(ctx, fmt.Sprintf("Error reading %q - removing from state", id.ID()))
state.RemoveResource(ctx)
return
}
diagnostics.AddError("Failed to retrieve resource", fmt.Errorf("reading %s: %+v", id, err).Error())
return
}
model.ID = basetypes.NewStringValue(id.ID())
output, err := buildOutputFromBody(responseBody, model.ResponseExportValues, nil)
if err != nil {
diagnostics.AddError("Failed to build output", err.Error())
return
}
model.Output = output
diagnostics.Append(state.Set(ctx, model)...)
}