Skip to content

[core]: allow empty struct member updates#3190

Merged
pierreprinetti merged 2 commits intogophercloud:masterfrom
kayrus:flavor-pointer
Dec 6, 2024
Merged

[core]: allow empty struct member updates#3190
pierreprinetti merged 2 commits intogophercloud:masterfrom
kayrus:flavor-pointer

Conversation

@kayrus
Copy link
Copy Markdown
Contributor

@kayrus kayrus commented Sep 27, 2024

Fixes #1332

@kayrus kayrus requested a review from a team September 27, 2024 08:01
@github-actions github-actions bot added edit:loadbalancer This PR updates loadbalancer code edit:compute This PR updates compute code semver:major Breaking change labels Sep 27, 2024
@coveralls
Copy link
Copy Markdown

coveralls commented Sep 27, 2024

Coverage Status

coverage: 78.726%. remained the same
when pulling c9703e7 on kayrus:flavor-pointer
into 8caccbb on gophercloud:master.

EmilienM
EmilienM previously approved these changes Oct 4, 2024
@EmilienM
Copy link
Copy Markdown
Contributor

EmilienM commented Oct 4, 2024

I've approved it but I need an extra pair of eyes on this one, ping @pierreprinetti

@pierreprinetti pierreprinetti added the hold Do not merge label Oct 4, 2024
Copy link
Copy Markdown
Member

@pierreprinetti pierreprinetti left a comment

Choose a reason for hiding this comment

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

I understand the value of changing all types to pointer types in UpdateOpts structs while keeping the omitempty tag, to make a clear difference between "I want to change this property" and "I don't want to change this property", including the case where the required new value happens to be the zero value for the type (and as a consequence wasn't sent to the server before this patch).

This technically is a superfluous change in some instances. For example, let's take the servers package. It's useless to use *string in Name, because the API refuses the empty string as a name. Same goes for accessIPv4 and accessIPv6. However, I agree with you that this change brings consistency and consistency is valuable.

My comments propose the addition of a convenience generic function that given a value, returns a pointer to it. It may make code more easily readable and reduce the LOC count of this patch. Please consider adding it in an internal package (I propose internal/ptr) to use it in both unit and acceptance tests.

name := tools.RandomString("TESTACCT-", 8)
flavorProfileUpdateOpts := flavorprofiles.UpdateOpts{
Name: tools.RandomString("TESTACCTUP-", 8),
Name: &name,
Copy link
Copy Markdown
Member

@pierreprinetti pierreprinetti Oct 4, 2024

Choose a reason for hiding this comment

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

Suggested change
Name: &name,
Name: ptr.To(tools.RandomString("TESTACCTUP-", 8)),

Description: description,
FlavorProfileId: flavorProfile.ID,
Enabled: true,
Enabled: new(bool),
Copy link
Copy Markdown
Member

@pierreprinetti pierreprinetti Oct 4, 2024

Choose a reason for hiding this comment

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

Suggested change
Enabled: new(bool),
Enabled: ptr.To(true),

Comment on lines +810 to +811
name := "new-name"
actual, err := servers.Update(context.TODO(), client, "1234asdf", servers.UpdateOpts{Name: &name}).Extract()
Copy link
Copy Markdown
Member

@pierreprinetti pierreprinetti Oct 4, 2024

Choose a reason for hiding this comment

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

Suggested change
name := "new-name"
actual, err := servers.Update(context.TODO(), client, "1234asdf", servers.UpdateOpts{Name: &name}).Extract()
actual, err := servers.Update(context.TODO(), client, "1234asdf", servers.UpdateOpts{Name: ptr.To("new-name")}).Extract()

Comment on lines +52 to +53
Name: &name,
AvailabilityZone: &availabilityZone,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please consider adding an internal convenience function to indirect values on-the-fly:

diff --git a/internal/ptr/to.go b/internal/ptr/to.go
new file mode 100644
index 00000000..0f2fd60f
--- /dev/null
+++ b/internal/ptr/to.go
@@ -0,0 +1,3 @@
+package ptr
+
+func To[T any](v T) *T { return &v }

After that, this can become:

Suggested change
Name: &name,
AvailabilityZone: &availabilityZone,
Name: ptr.To("new_aggregate_name"),
AvailabilityZone: ptr.To("new_azone"),

As a byproduct, it's a function we can point users to in case they want to copy-paste.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

why internal? this can be reused in other packages. also it would be helpful to have a helper to get a pointer value on-the-fly. and if it's a nil, return an empty struct.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Internal so that it doesn't increase the package's API. I don't think we want that function to be part of the exported Gophercloud funtions.

it would be helpful to have a helper to get a pointer value on-the-fly. and if it's a nil, return an empty struct

That looks complex. Do you envision that as another convenience function for testing? Would you use that in this PR?

updateOpts := secgroups.UpdateOpts{
Name: newName,
Name: &newName,
Description: &description,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This can become:

Suggested change
Description: &description,
Description: ptr.To(""),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll keep this as is, since description is used below in code.

"name": "Basic",
"description": "A basic standalone Octavia load balancer.",
"enabled": true,
"enabled": false,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This can be reverted once you apply my suggestion above

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

no, we want to ensure that this can be set to false.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK; but then please add a new test to verify the new functionality, and leave this old test here doing its job of testing regressions :)

Name: "Basic",
Description: "A basic standalone Octavia load balancer.",
Enabled: true,
Enabled: new(bool),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Enabled: new(bool),
Enabled: ptr.To(true),

Comment on lines +113 to +115
Name: &name,
Description: &description,
Enabled: &enabled,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

consider using ptr.To

@kayrus kayrus force-pushed the flavor-pointer branch 4 times, most recently from a43d466 to 84deba4 Compare October 9, 2024 20:00
@github-actions github-actions bot added the edit:actions This PR updates GitHub Actions code label Oct 9, 2024
Comment on lines +7 to +13
func From[T any](p *T) T {
if p == nil {
var v T
return v
}
return *p
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't seem to be used anywhere. Please remove

Octavia Flavor's `enabled` is true by default
@pierreprinetti pierreprinetti removed the hold Do not merge label Dec 6, 2024
Copy link
Copy Markdown
Member

@pierreprinetti pierreprinetti left a comment

Choose a reason for hiding this comment

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

Thanks! This is for v3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

edit:actions This PR updates GitHub Actions code edit:compute This PR updates compute code edit:loadbalancer This PR updates loadbalancer code semver:major Breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JSON marshalling and omitempty for empty strings and bools

4 participants