Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add hashing function on region attributes #286

Merged
merged 4 commits into from
Aug 26, 2022
Merged

Conversation

MircoT
Copy link
Contributor

@MircoT MircoT commented Aug 11, 2022

With this fix is resolved the #281

@scraly scraly added the v0.20 label Aug 23, 2022
@scraly
Copy link
Collaborator

scraly commented Aug 23, 2022

Tested and now we have all the regions displayed in regions_attributes field.

Before:

# ovh_cloud_project_network_private.vnet:
resource "ovh_cloud_project_network_private" "vnet" {
    id                 = "pn-1083678_5"
    name               = "test"
    regions            = [
        "GRA7",
        "SBG5",
    ]
    regions_attributes = [
        {
            openstackid = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
            region      = "SBG5"
            status      = "ACTIVE"
        },
    ]
    regions_status     = [
        {
            region = "SBG5"
            status = "ACTIVE"
        },
    ]
    service_name       = "xxxxxxxxx"
    status             = "ACTIVE"
    type               = "private"
    vlan_id            = 5
}

After:

# ovh_cloud_project_network_private.vnet:
resource "ovh_cloud_project_network_private" "vnet" {
    id                 = "pn-1083678_5"
    name               = "test"
    regions            = [
        "GRA7",
        "SBG5",
    ]
    regions_attributes = [
        {
            openstackid = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
            region      = "GRA7"
            status      = "ACTIVE"
        },
        {
            openstackid = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
            region      = "SBG5"
            status      = "ACTIVE"
        },
    ]
    regions_status     = [
        {
            region = "SBG5"
            status = "ACTIVE"
        },
    ]
    service_name       = "xxxxxx"
    status             = "ACTIVE"
    type               = "private"
    vlan_id            = 5
}

func HashMapRegionAttributes(v interface{}) int {
attributes, ok := v.(map[string]interface{})
if !ok {
return 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you returning 0?
In which case should we obtain ok == false?
Is it possible to return an error message or something?
Thanks

Copy link
Contributor Author

@MircoT MircoT Aug 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I'm returning 0 to be conformed to the hashing function signature, that is func(interface{}) int. Said that, the conversion check regarding the v interface is just to ensure that everything goes well but, in case of any failure, the only returning option for this signature is an integer and not an error. Maybe, a -1 is a better option in place of returning 0.

However, since the schema should not change, that conversion check is just a stretch. Let me know the way is better to modify. Also, having a code like this is an option:

// HashMapRegionAttributes creates an hash for the region attributes.
func HashMapRegionAttributes(v interface{}) int {
	attributes := v.(map[string]interface{})
	builder := strings.Builder{}

	for _, key := range []string{"status", "region", "openstackid"} {
		value, inMap := attributes[key]
		if inMap {
			stringValue, ok := value.(string)
			if ok {
				builder.WriteString(stringValue)
			}
		}
	}

	return schema.HashString(builder.String())
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, I opted for that last option. I hope it is the best way to approach the problem.

@MircoT MircoT requested a review from scraly August 24, 2022 08:40
@scraly
Copy link
Collaborator

scraly commented Aug 24, 2022

The error must be handled.

For example, the method can return an int and an error:

// HashMapRegionAttributes creates an hash for the region attributes.
func HashMapRegionAttributes(v interface{}) (int, error) {
    attributes, ok := v.(map[string]interface{})
    if !ok {
        return -1, errors.New("bad cast...")
    }

    builder := strings.Builder{}
...

@MircoT
Copy link
Contributor Author

MircoT commented Aug 24, 2022

@scraly it is not possible to handle the error in that function because in a Terraform Schema the Set field is a SchemaSetFunc that should be this specific type:

type SchemaSetFunc func(interface{}) int

Consequently, returning a tuple instead of an integer is not an option at this level.

@MircoT
Copy link
Contributor Author

MircoT commented Aug 25, 2022

The error must be handled.

For example, the method can return an int and an error:

// HashMapRegionAttributes creates an hash for the region attributes.
func HashMapRegionAttributes(v interface{}) (int, error) {
    attributes, ok := v.(map[string]interface{})
    if !ok {
        return -1, errors.New("bad cast...")
    }

    builder := strings.Builder{}
...

Another option that doesn't involve many code changes in resource creation could be something like this:

"regions_attributes": {
		Type:     schema.TypeList,
		Computed: true,
		Elem: &schema.Resource{
			Schema: map[string]*schema.Schema{
				"status": {
					Type:     schema.TypeString,
					Required: true,
				},

				"region": {
					Type:     schema.TypeString,
					Computed: true,
				},

				"openstackid": {
					Type:     schema.TypeString,
					Computed: true,
				},
			},
		},
	}

With such a solution, the helper function HashMapRegionAttributes for the set is not required and the logic behind the list creation is still the same. Otherwise, if a strict check of the element structures (beyond the schema) is necessary, the TypeMap could be used with a SchemaValidateDiagFunc but, in that case, the resource creation has to be changed too.

Which one is better for this case @scraly ?

PS: of course, in the case of TypeList utilization, I'll remove this PR and make a new one with only that difference

@scraly
Copy link
Collaborator

scraly commented Aug 25, 2022

Hi, after thinking,
is it possible to:

  • move the function to cloud_project_network_private_helpers.go because the function should. be only used by the resource
  • rename the function to RegionAttributesHash for example
  • add an error log when the cast is failing and a panic

Thanks

Copy link
Collaborator

@scraly scraly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, after thinking,
is it possible to:

  • move the function to cloud_project_network_private_helpers.go because the function should. be only used by the resource
  • rename the function to RegionAttributesHash for example
  • add an error log when the cast is failing and a panic

Thanks

@MircoT
Copy link
Contributor Author

MircoT commented Aug 25, 2022

Hi, after thinking, is it possible to:

  • move the function to cloud_project_network_private_helpers.go because the function should. be only used by the resource
  • rename the function to RegionAttributesHash for example
  • add an error log when the cast is failing and a panic

Thanks

All the requirements should be satisfied, let me know if something else is missing or if the error description is not conforming to the others in the module.

@MircoT MircoT requested a review from scraly August 25, 2022 08:29
Copy link
Collaborator

@scraly scraly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only thing left to comply with the whole list is to put the function in a file next to the resource, for example: cloud_project_network_private_helpers.go :)

@MircoT MircoT requested a review from scraly August 25, 2022 14:28
@MircoT
Copy link
Contributor Author

MircoT commented Aug 26, 2022

The only thing left to comply with the whole list is to put the function in a file next to the resource, for example: cloud_project_network_private_helpers.go :)

Right... I just misunderstood the previous message...

Copy link
Collaborator

@scraly scraly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, now it's perfect :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants