Port: add propagationUplinkStatus field#641
Conversation
|
weird... the uplink_status_propagation extension was not added to the devstack deployment. I tested locally and it only works by setting Has anyone ever seen something like this? |
8cbef64 to
4d21547
Compare
|
Ok, here we go. I needed to add the neutron plugin on CI so that devstack can run this line and enable uplink-status-propagation accordingly. However, it looks like that Dalmatian release doesn't enable the ability to update About the job failing on Flamingo I really don't get the why. The E2E job has failed in cc. @mandre I'll wait for you feedback before making any additional change. |
| // propagateUplinkStatus represents the uplink status propagation of | ||
| // the port. | ||
| // +optional | ||
| PropagateUplinkStatus *bool `json:"propagateUplinkStatus,omitempty"` |
There was a problem hiding this comment.
We've discussed this privately already, after you brought the issue to my attention: gophercloud implements the PropagateUplinkStatus in the response Port structure as a bool while it should really be a *bool with omitempty, and because of this we can't reliably know the status for PropagateUplinkStatus. I suggest that until the issue if fixed in gophercloud, we make that field immutable.
There was a problem hiding this comment.
It's been a while and I don't remember all of the discussion. From reading the PR comments again, I believe we're past the gophercloud limitation (thanks to custom unmarshalling) but we still need to make the field immutable because dalmatien doesn't support updating the field. If that's effectively the case, we should add that as a comment so we know when we can change that behavior.
There was a problem hiding this comment.
Yes, you're absolutely right. I'll add this comment.
I re-ran this job and the error is gone. I was most likely a flake (bound to happen as we add more tests). |
|
@mandre let me know when you think it is ready to go, I can squash the commits to make the PR cleaner. :) |
| // propagateUplinkStatus represents the uplink status propagation of | ||
| // the port. | ||
| // +optional | ||
| PropagateUplinkStatus *bool `json:"propagateUplinkStatus,omitempty"` |
There was a problem hiding this comment.
It's been a while and I don't remember all of the discussion. From reading the PR comments again, I believe we're past the gophercloud limitation (thanks to custom unmarshalling) but we still need to make the field immutable because dalmatien doesn't support updating the field. If that's effectively the case, we should add that as a comment so we know when we can change that behavior.
| PropagateUplinkStatusPtr *bool `json:"propagate_uplink_status,omitempty"` | ||
| } | ||
|
|
||
| func (p *PortExt) UnmarshalJSON(b []byte) error { |
There was a problem hiding this comment.
This custom unmarshaller omits portsecurity.PortSecurityExt or portsbinding.PortsBindingExt meaning that they'll always have the zero value (it's weird that we do not detect this bug via the tests, don't we have coverage for those fields?).
There was a problem hiding this comment.
It is something that I was in doubt about... I'm not sure, and if you can correct me if I'm wrong, I'll appreciate it, but it looks like Gophercloud uses reflection to populate the result rather than simply using a json.Unmarshal, am I wrong?
https://github.com/gophercloud/gophercloud/blob/main/results.go#L70
You're right that they will always have the zero value, but maybe in the above phase, the fields are populated using reflection. I need to better understand this. Any initial thought?
There was a problem hiding this comment.
A well crafted test should give us the answer.
There was a problem hiding this comment.
Sorry for the late response.
The idea of this test is to show that using ports.Get(...).ExtractInto(&p), the fields are populated even though they're not explicitly set in the UnmarshalJSON function, as you highlighted in your initial comment, unlike using json.Unmarshal directly, which calls the custom Unmarshal and ignores the PortSecurityEnabled and PortBindings.
There was a problem hiding this comment.
After understanding more about how the parse actually works, I've decided to add PortSecurityExt and PortsBindingExt to the Unmarshal function.
This helps us especially when listing ports because we are not using the default Gophercloud's Extract mechanisms, and we do need to populate fields using the unmarshaler function.
There was a problem hiding this comment.
We're now missing PortTrustedVIFExt as well 😢
| @@ -172,13 +191,30 @@ func (c networkClient) UpdateFloatingIP(ctx context.Context, id string, opts flo | |||
|
|
|||
| func (c networkClient) ListPort(ctx context.Context, opts ports.ListOptsBuilder) iter.Seq2[*PortExt, error] { | |||
There was a problem hiding this comment.
We shouldn't have to update ListPort I believe.
There was a problem hiding this comment.
IIRC, there was a failing test, and the solution was to change the ListPort function, but I'll double-check this to confirm what exactly the error was.
There was a problem hiding this comment.
After discussion, we found a potential bug in Gophercloud, and a PR has been created. More information is there.
There was a problem hiding this comment.
So, do we also need the same thing for GetPort (and potentially CreatePort and UpdatePort)? It looks to me like we should wait for a new gophercloud that includes your fix.
There was a problem hiding this comment.
As long as I can see, we don't need. For Get, Create, and Update Port, all of them pass a struct to the ExtractInto function, making the function pass through this path. At the end of execution, the unmarshaling of non-struct field is handled by the err = json.Unmarshal(b, &to).
I also don't like the way it is, so it is ok for me to wait for a new release and get it properly fixed. Wdyt?
There was a problem hiding this comment.
That would be my preference as well.
|
@mandre I'm working again to have this PR merged. A lot of work has been done since the last commit, so I'll rebase and start addressing the comments. |
0f1e900 to
60786e3
Compare
|
@mandre let me know when you think it is good. I'd like to squash the commits. keeping the history clear 🤌 |
|
@winiciusallan Just looked at your changes again. They look good to me now. Would you like to do the rebase yourself, to fix the conflicts and squash what needs squashing, or would you like me to take care of it? |
|
@mandre I will do this, thanks for asking! |
60786e3 to
1749c64
Compare
| PropagateUplinkStatusPtr *bool `json:"propagate_uplink_status,omitempty"` | ||
| } | ||
|
|
||
| func (p *PortExt) UnmarshalJSON(b []byte) error { |
There was a problem hiding this comment.
We're now missing PortTrustedVIFExt as well 😢
| PropagateUplinkStatusPtr *bool `json:"propagate_uplink_status,omitempty"` | ||
| } | ||
|
|
||
| func (p *PortExt) UnmarshalJSON(b []byte) error { |
There was a problem hiding this comment.
May I suggest we add a comment to drop this custom unmarshaller once we're on the next major version of gophercloud (v3). The function is going to be difficult to maintain, and I'd like to drop it at the first occasion.
There was a problem hiding this comment.
Sure! Will add it.
| @@ -172,13 +191,30 @@ func (c networkClient) UpdateFloatingIP(ctx context.Context, id string, opts flo | |||
|
|
|||
| func (c networkClient) ListPort(ctx context.Context, opts ports.ListOptsBuilder) iter.Seq2[*PortExt, error] { | |||
There was a problem hiding this comment.
So, do we also need the same thing for GetPort (and potentially CreatePort and UpdatePort)? It looks to me like we should wait for a new gophercloud that includes your fix.
This PR introduces the propagationUplinkStatus
https://docs.openstack.org/api-ref/network/v2/index.html#uplink-status-propagation
Notes:
I've decided to keep the default value for that field asfalse, even if the doc says that the default value istrue. The reason is that in environments where this extension is not enabled, we can't update that field and it always returns false, so if we enforce it as true, it may raise an error. So if the user wants to enable it, they must explicitly define it.edit:
true. Otherwise, it'll benilPartial #616