orange-cloudavenue / terraform-provider-cloudavenue

Terraform Cloud Avenue provider
https://registry.terraform.io/providers/orange-cloudavenue/cloudavenue
Mozilla Public License 2.0
14 stars 3 forks source link

[Bug]: Error: Provider produced inconsistent result after apply. Vm creation. Same code executed but different results (Identical CI). #737

Open ValentinPhB opened 4 months ago

ValentinPhB commented 4 months ago

Terraform Core Version

1.7.3

Cloud Avenue Provider Version

0.15.4

Affected Resource(s)

Hi,

ressource cloudavenue_vm https://registry.terraform.io/providers/orange-cloudavenue/cloudavenue/latest/docs/resources/vm

Expected Behavior

Hi,

If I run an unchanged CI twice, I should get the same result.

Actual Behavior

Hi,

Our CI executes the same stage at different times and gets different results. The code, Terraform version, and provider version remain unchanged.

Relevant Error/Panic Output Snippet

No response

Terraform Configuration Files

Hi,

terraform {
  required_providers {
    cloudavenue = {
      source  = "orange-cloudavenue/cloudavenue"
      version = "0.15.4"
    }
  }
}

Steps to Reproduce

Hi,

Here is the code used:

package test

import (
    "fmt"
    "os"
    "strconv"
    "testing"

    "github.com/gruntwork-io/go-commons/files"
    "github.com/gruntwork-io/terratest/modules/random"
    "github.com/gruntwork-io/terratest/modules/terraform"
    "github.com/stretchr/testify/assert"
)

// Using var.key_value_security_tags_list for security tags
func TestTerraformAll(t *testing.T) {
    // Create a unique name with dynamic suffix
    uniqueID := random.UniqueId()

    // vapp has to exists
    inputVAppName := "vapp-tnr-vm"

    // catalog has to exist
    InputCatalogName := "Orange-Linux-Internal"

    // OS template has to exist
    inputOs := "RHEL_7.9"

    // network routed of the vapp has to exist and be the same has the vapp
    inputNetworkRouted := "obsitlabiaas"

    //  Input Values
    inputVmName := fmt.Sprintf("ci-lvm-test-%s", uniqueID)
    inputVmDescription := "Vm create by Ci-tests"
    inputCpuHotAddEnabled := false
    inputCpu := 3
    inputCpuCores := 3
    inputMemory := 3
    expectedMemory := inputMemory * 1024
    inputMemoryHotAddEnabled := false
    inputVmResourceNetworksType := "org"
    inputVmResourceNetworksIpAllocationMode := "POOL"
    inputVmResourceNetworksIsPrimary := true

    inputNetwork := map[string]any{
        "type":               inputVmResourceNetworksType,
        "ip_allocation_mode": inputVmResourceNetworksIpAllocationMode,
        "is_primary":         inputVmResourceNetworksIsPrimary,
        "name":               inputNetworkRouted,
    }
    listNetworks := []any{inputNetwork}

    inputVmResourceSettingsCustomizationAllowLocalAdminPassword := false
    inputVmResourceSettingsCustomizationAutoGeneratePassword := false
    inputVmResourceSettingsCustomizationChangeSid := false
    inputVmResourceSettingsCustomizationEnabled := false
    inputVmResourceSettingsCustomizationForce := false
    inputVmResourceSettingsCustomizationHostname := fmt.Sprintf("custom-hostname-%s", uniqueID)
    inputVmResourceSettingsCustomizationJoinDomain := false
    inputVmResourceSettingsCustomizationJoinOrgDomain := false
    inputVmResourceSettingsCustomizationMustChangePasswordOnFirstLogin := false
    inputVmResourceSettingsExposeHardwareVirtualization := false
    inputPowerOn := true
    inputKeyValueSecurityTagsList := map[string]interface{}{
        "firstKey":   "firstValue",
        "secondtKey": "secondValue",
    }

    // Install the provider.tf with defered deletion
    defer os.Remove("../provider.tf")
    files.CopyFile("provider.tf", "../provider.tf")

    // retryable errors in terraform testing.
    terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
        // The path to where our Terraform code is located
        TerraformDir: "../",

        // Variables to pass to our Terraform code using -var options
        Vars: map[string]interface{}{
            "vapp_name":                 inputVAppName,
            "catalog_name":              InputCatalogName,
            "os":                        inputOs,
            "network_routed":            inputNetworkRouted,
            "vm_name":                   inputVmName,
            "vm_description":            inputVmDescription,
            "vm_cpu_hot_add_enabled":    inputCpuHotAddEnabled,
            "cpu":                       inputCpu,
            "cpu_cores":                 inputCpuCores,
            "memory":                    inputMemory,
            "vm_memory_hot_add_enabled": inputMemoryHotAddEnabled,
            "vm_resource_networks":      listNetworks,
            "vm_resource_settings_customization_allow_local_admin_password":          inputVmResourceSettingsCustomizationAllowLocalAdminPassword,
            "vm_resource_settings_customization_auto_generate_password":              inputVmResourceSettingsCustomizationAutoGeneratePassword,
            "vm_resource_settings_customization_change_sid":                          inputVmResourceSettingsCustomizationChangeSid,
            "vm_resource_settings_customization_enabled":                             inputVmResourceSettingsCustomizationEnabled,
            "vm_resource_settings_customization_force":                               inputVmResourceSettingsCustomizationForce,
            "vm_resource_settings_customization_hostname":                            inputVmResourceSettingsCustomizationHostname,
            "vm_resource_settings_customization_join_domain":                         inputVmResourceSettingsCustomizationJoinDomain,
            "vm_resource_settings_customization_join_org_domain":                     inputVmResourceSettingsCustomizationJoinOrgDomain,
            "vm_resource_settings_customization_must_change_password_on_first_login": inputVmResourceSettingsCustomizationMustChangePasswordOnFirstLogin,
            "vm_resource_settings_expose_hardware_virtualization":                    inputVmResourceSettingsExposeHardwareVirtualization,
            "key_value_security_tags_list":                                           inputKeyValueSecurityTagsList,
            "power_on":                                                               inputPowerOn,
        },
    })

    // At the end of the test, run `terraform destroy` to clean up any resources that were created.
    defer terraform.Destroy(t, terraformOptions)

    // Run `terraform init` and `terraform apply`. Fail the test if there are any errors.
    terraform.InitAndApply(t, terraformOptions)

    // Run `terraform output` to get the value of an output variable
    outputVapp := terraform.Output(t, terraformOptions, "vapp_name")
    outputOsVersion := terraform.Output(t, terraformOptions, "vm_os")
    outputVmName := terraform.Output(t, terraformOptions, "vm_name")
    outputVmDescription := terraform.Output(t, terraformOptions, "vm_description")

    outputCpuHotEnabled, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_cpu_hot_add_enabled"))
    outputCpu, _ := strconv.Atoi(terraform.Output(t, terraformOptions, "vm_cpu"))
    outputCpusCores, _ := strconv.Atoi(terraform.Output(t, terraformOptions, "vm_cpus_cores"))
    outputMemory, _ := strconv.Atoi(terraform.Output(t, terraformOptions, "vm_memory"))
    outputMemoryHotAddEnabled, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_memory_hot_add_enabled"))
    outputVmResourceNetworkType := terraform.Output(t, terraformOptions, "vm_resource_networks_type")
    outputVmResourceNetworkIpAllocationMode := terraform.Output(t, terraformOptions, "vm_resource_networks_ip_allocation_mode")
    outputVmResourceNetworkIsPrimary, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_networks_is_primary"))
    outputVmResourceSettingsCustomizationAllowLocalAdminPassword, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_customization_allow_local_admin_password"))
    outputVmResourceSettingsCustomizationAutoGeneratePassword, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_customization_auto_generate_password"))
    outputVmResourceSettingsCustomizationChangeSid, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_customization_change_sid"))
    outputVmResourceSettingsCustomizationEnabled, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_customization_enabled"))
    outputVmResourceSettingsCustomizationForce, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_customization_force"))
    outputVmResourceSettingsCustomizationHostname := terraform.Output(t, terraformOptions, "vm_resource_settings_customization_hostname")
    outputVmResourceSettingsCustomizationJoinDomain, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_customization_join_domain"))
    outputVmResourceSettingsCustomizationJoinOrgDomain, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_customization_join_org_domain"))
    outputVmResourceSettingsCustomizationMustChangePasswordOnFirstLogin, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_customization_must_change_password_on_first_login"))
    outputVmResourceSettingsExposeHardwareVirtualization, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "vm_resource_settings_expose_hardware_virtualization"))
    outputPowerOn, _ := strconv.ParseBool(terraform.Output(t, terraformOptions, "power_on"))

    // Check that the outputs match the expected values
    assert.Equal(t, inputVAppName, outputVapp)
    assert.Equal(t, inputOs, outputOsVersion)
    assert.Equal(t, inputVmName, outputVmName)
    assert.Equal(t, inputVmDescription, outputVmDescription)
    assert.Equal(t, inputCpuHotAddEnabled, outputCpuHotEnabled)
    assert.Equal(t, inputCpu, outputCpu)
    assert.Equal(t, inputCpuCores, outputCpusCores)
    assert.Equal(t, expectedMemory, outputMemory)
    assert.Equal(t, inputMemoryHotAddEnabled, outputMemoryHotAddEnabled)
    assert.Equal(t, inputVmResourceNetworksType, outputVmResourceNetworkType)
    assert.Equal(t, inputVmResourceNetworksIpAllocationMode, outputVmResourceNetworkIpAllocationMode)
    assert.Equal(t, inputVmResourceNetworksIsPrimary, outputVmResourceNetworkIsPrimary)
    assert.Equal(t, inputVmResourceSettingsCustomizationAllowLocalAdminPassword, outputVmResourceSettingsCustomizationAllowLocalAdminPassword)
    assert.Equal(t, inputVmResourceSettingsCustomizationAutoGeneratePassword, outputVmResourceSettingsCustomizationAutoGeneratePassword)
    assert.Equal(t, inputVmResourceSettingsCustomizationChangeSid, outputVmResourceSettingsCustomizationChangeSid)
    assert.Equal(t, inputVmResourceSettingsCustomizationEnabled, outputVmResourceSettingsCustomizationEnabled)
    assert.Equal(t, inputVmResourceSettingsCustomizationForce, outputVmResourceSettingsCustomizationForce)
    assert.Equal(t, inputVmResourceSettingsCustomizationHostname, outputVmResourceSettingsCustomizationHostname)
    assert.Equal(t, inputVmResourceSettingsCustomizationJoinDomain, outputVmResourceSettingsCustomizationJoinDomain)
    assert.Equal(t, inputVmResourceSettingsCustomizationJoinOrgDomain, outputVmResourceSettingsCustomizationJoinOrgDomain)
    assert.Equal(t, inputVmResourceSettingsCustomizationMustChangePasswordOnFirstLogin, outputVmResourceSettingsCustomizationMustChangePasswordOnFirstLogin)
    assert.Equal(t, inputVmResourceSettingsExposeHardwareVirtualization, outputVmResourceSettingsExposeHardwareVirtualization)
    assert.Equal(t, inputPowerOn, outputPowerOn)
}

Debug Output

Hi, Due to the character limit, I'm attaching screenshots here. I can grant you access to the relevant project if you'd like.

Here are the results for a CI executed on February 1st, 2024 : image image image image image image image

Here are the results for a CI executed on February 28, 2024 : image image image image image image image

Panic Output

No response

Important Factoids

Hi ,

For both executions of our CI, the context remains unchanged :

image hashicorp/terraform:1.5.7 go version go1.20.11 linux/amd64 All go libraries were checked.

Installing orange-cloudavenue/cloudavenue v0.15.4


Resume :

Same CI executed on February 1st and 28, 2024. Only the one from the 28th presents the following error during VM creation: image

References

No response

Would you like to implement a fix?

None

azrod commented 1 month ago

Hi @ValentinPhB,

I'm found your problem. The customization settings are editable only if Guest Customization is enabled.

The settings Auto Generate Password is enabled in your vapp template but the guest customization is disabled. So the parameter auto_generate_password = false in your terraform configuration is not applied.

If you do not know the state of the fields provided by the vapp template, it's recommended that you configure terraform implicity because this attribute is "Optional and Compute". If you define no configuration for this field the provider call API and get the value.

Regards