Hi @bflad ! Thank you for you explanations, I confirm that I don’t have CustomizeDiff
defined and here is my UpdateFunction
:
func resourceContentUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var diags diag.Diagnostics
c := m.(*pc.Client)
childComponents, err := serializeChildComponents(d.Get("container.0").(map[string]interface{}), ctx)
if err != nil {
diags = append(diags, diag.Diagnostic{
Severity: diag.Error,
Summary: "Unable to serialize child components",
Detail: fmt.Sprintf("Error when serializing child components: %s", err.Error()),
})
return diags
}
co := content.Content{
ID: d.Id(),
Name: d.Get("name").(string),
Description: d.Get("description").(string),
Type: d.Get("type").(string),
Reward: int64(d.Get("reward").(int)),
RootComponent: content.Component{
ID: d.Get("container.0.id").(string),
Orientation: d.Get("container.0.orientation").(string),
Type: "container",
Data: content.ComponentData{
Components: childComponents,
},
},
Data: content.ContentData{},
}
_, err = c.UpdateContent(co)
if err != nil {
diags = append(diags, diag.Diagnostic{
Severity: diag.Error,
Summary: "Unable to update content",
Detail: fmt.Sprintf("Error when updating content: %s", err.Error()),
})
return diags
}
d.Set("last_update", d.Set("last_updated", time.Now().Format(time.RFC850)))
tflog.Info(ctx, fmt.Sprintf("Updated Content %s", d.Id()))
return resourceContentRead(ctx, d, m)
}
To completely understand it you’ll need the serializeChildComponents
function which is a little bit complicated and translate the schema to a struct
:
func serializeChildComponents(rootComponent map[string]interface{}, ctx context.Context) ([]content.Component, error) {
length := 0
for key, val := range rootComponent {
if key == "markdown" || key == "editor" {
length += len(val.(*schema.Set).List())
}
if key == "container" && val != nil {
length += len(val.([]interface{}))
}
}
tflog.Debug(ctx, fmt.Sprintf("Serializing root Component %s with %d child components", rootComponent["id"], length))
childComponents := make([]content.Component, length)
positions := make([]bool, length)
for key, val := range rootComponent {
switch key {
case "markdown":
for _, v := range val.(*schema.Set).List() {
markdown := v.(map[string]interface{})
position := markdown["position"].(int)
if position > length {
return nil, fmt.Errorf("position %d is greater than the number of child components %d", position, length)
}
positions[position-1] = true
childComponents[position-1] = content.Component{
ID: markdown["id"].(string),
Type: "markdown",
Data: content.ComponentData{
Markdown: markdown["content"].(string),
},
}
}
case "editor":
for _, v := range val.(*schema.Set).List() {
editor := v.(map[string]interface{})
languages := make([]content.Language, 0)
for _, language := range editor["language_settings"].(*schema.Set).List() {
languages = append(languages, content.Language{
DefaultCode: language.(map[string]interface{})["default_code"].(string),
Language: language.(map[string]interface{})["language"].(string),
Version: language.(map[string]interface{})["version"].(string),
})
}
validators := make([]content.Validator, 0)
for _, validator := range editor["validator"].(*schema.Set).List() {
inputs := make([]string, len(validator.(map[string]interface{})["inputs"].([]interface{})))
for key, val := range validator.(map[string]interface{})["inputs"].([]interface{}) {
inputs[key] = val.(string)
}
outputs := make([]string, len(validator.(map[string]interface{})["outputs"].([]interface{})))
for key, val := range validator.(map[string]interface{})["outputs"].([]interface{}) {
outputs[key] = val.(string)
}
validators = append(validators, content.Validator{
ID: validator.(map[string]interface{})["id"].(string),
IsHidden: validator.(map[string]interface{})["is_hidden"].(bool),
Input: content.ValidatorInput{
Stdin: inputs,
},
Output: content.ValidatorOutput{
Stdout: outputs,
},
})
}
hints := make([]content.ItemIdentifier, 0)
for _, item := range editor["hint"].([]interface{}) {
hints = append(hints, content.ItemIdentifier{
ID: item.(string),
})
}
position := editor["position"].(int)
if position > length {
return nil, fmt.Errorf("position %d is greater than the number of child components %d", position, length)
}
positions[position-1] = true
childComponents[position-1] = content.Component{
ID: editor["id"].(string),
Type: "editor",
Data: content.ComponentData{
EditorSettings: content.EditorSettings{
Languages: languages,
},
Validators: validators,
Items: hints,
},
}
}
case "container":
for _, v := range val.([]interface{}) {
container := v.(map[string]interface{})
position := container["position"].(int)
if position > length {
return nil, fmt.Errorf("position %d is greater than the number of child components %d", position, length)
}
positions[position-1] = true
containerChildComponents, err := serializeChildComponents(container, ctx)
if err != nil {
return nil, err
}
childComponents[position-1] = content.Component{
ID: container["id"].(string),
Type: "container",
Data: content.ComponentData{
Components: containerChildComponents,
},
Orientation: container["orientation"].(string),
}
}
}
}
for i, position := range positions {
if !position {
return nil, fmt.Errorf("child component at position %d is missing, this is probably due to duplicate position in the container, please check that your positions go from 1 to %d", i+1, length)
}
}
return childComponents, nil
}
In fact, after some explanation, the problem that I’m facing may be related to this function instead of the Update
process of Terraform.
Thank you for your help !