-
Notifications
You must be signed in to change notification settings - Fork 0
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
Waf resource import #17
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whilst this solution is simple and elegant and is suitable for 98% of use-cases it solves, the underlying problem it is trying to solve is a much wider issue across the go-fastly client (not just the WAF related structs) and API clients in general.
This HasChanges()
implementation doesn't account for the fact that a user may genuinely be wanting to set all of the values to their zero values (0
, ""
, false
etc).
The problem is the combination of Go's type zero values, JSON marshalling with the omitempty
struct field tag, and a users intent to actually set a zero value. This blog post does a much better job at explaining the problem and well worth a read: https://willnorris.com/2014/05/go-rest-apis-and-pointers/
As the post suggests, the more robust solution would be to change the struct field values to all be pointers instead of the underlying type value. However - whilst I think this is the correct approach - this would be different to how all other structures in the go-fastly
client are modelled and places some pain on the library users to convert their inputs to pointers and do nil pointer checks when consuming.
Another option would be for us to create an optional type structure to model values, such as this pattern i've used in other projects:
type Optional struct {
Valid bool
}
func (o *Optional) Set() error {
o.Valid = true
return nil
}
// OptionalString models an optional string flag value.
type OptionalString struct {
Optional
Value string
}
// OptionalBool models an optional boolean flag value.
type OptionalBool struct {
Optional
Value bool
}
// etc...
However I think such patterns would be an even larger change for the client and consumers, as they have to know to use the inner .Value
field to access the underlying data. As an aside, I'm a big van of real Optional types from languages like Scala and Rust, but thats a discussion for another day.
TL;DR is i'm ok with this implementation as is, however I'm writing this to open the wider discussion of how we solve this problem for the client going forward and would like yours and other thoughts on it.
Thanks @phamann for the detailed explanation. I see how using pointers would make the update more accurate and flexible in general terms. I like the Optional pattern and the semantics it brings to the implementation, but I agree it would be a bigger change for go-fastly SDK users to adopt. Given that the current implementation of the WAF configuration doesn't work for 100% of the cases, we'd like to change this PATCH endpoint's to use pointers and document the reason why this is different from the others endpoints. We can have further discussions on making a bigger change so this issue is addressed across the entire SDK. Please let us know if you agree with the change |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Therefore, as per the discussion in the PR and in-person, can we please change the struct field values to use pointers and document why 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
fastly/waf_version.go
Outdated
@@ -226,60 +226,72 @@ func (c *Client) GetWAFVersion(i *GetWAFVersionInput) (*WAFVersion, error) { | |||
return &wafVer, nil | |||
} | |||
|
|||
// UpdateWAFVersionInput is used as input to the UpdateWAFVersion function. | |||
// UpdateWAFVersionInput is used as input to the UpdateWAFVersion function. This struct uses pointers due to the problem | |||
// detailed on this issue https://trello.com/c/dbF8uqKn. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
happy to have this in trello, as this is public probably make sense to reported as a GitHub issue (enhancement)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to the PR link
@@ -160,92 +160,92 @@ func TestClient_WAF_Versions(t *testing.T) { | |||
|
|||
func verifyWAFVersionUpdate(t *testing.T, i *UpdateWAFVersionInput, o *WAFVersion) { | |||
|
|||
if i.WAFVersionID != o.ID { | |||
t.Errorf("expected %s waf: got %s", i.WAFVersionID, o.ID) | |||
if *i.WAFVersionID != o.ID { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[IDEA] use testify to manage assertions,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but probably a bigger change so that it is used it consistently across all tests. @phamann any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer not to introduce that change in this pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 LGTM other than minor comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
* Introducing waf version struct method to check for custom emptiness * Using pointers on the WAf version update endpoint
* Introducing waf version struct method to check for custom emptiness * Using pointers on the WAf version update endpoint
* Service waf component (#5) * service waf component new API implemented * Waf configuration resource (#6) * waf version (configuration) API implemented * Waf active rules (#9) * WAF active rules implementation * Waf rules (#10) * WAF rules related endpoints implementation * Waf config resource deletion (#12) * create empty waf version endpoint implemented * Waf disable enable (#14) * making WAF enable and disable functions consistent with rest * introducing a maximum batch size exclusive for WAF requests * Waf resource import (#17) * Introducing waf version struct method to check for custom emptiness * Using pointers on the WAf version update endpoint * Cleaning up the old API remaining code (#18) * Update enable/disable WAF API * Update WAF active rules and WAF fixtures * Remove enable/disable WAF API * Fix type assertion for linter * Fix error message capitalisation for linter * Update waf_versions lock API * Update waf_versions activate API * Add LastDeploymentStatus so clients can deal with async deploys * Add testing for LastDeploymentStatus * Apply suggestions from code review * Fix fixtures for WAF tests * Setting go.mod package to v2 * Adding WAF Exclusion endpoints to go-fastly client Co-authored-by: Zsolt Balvanyos <5632209+ZsoltBalvanyos@users.noreply.github.com> * Changing WAF Exclusion terminology to WAF Rule Exclusion * Changing Include field to be a Slice instead of a comma-separated string * field consistency: ServiceID, ServiceVersion, DictionaryID, PoolID * use pointers as field values for optional basic types reference: https://willnorris.com/2014/05/go-rest-apis-and-pointers/ * Implement /stats/field API Fixes fastly#214 * README consistency with updated field identifiers * modernize the markdown syntax for defining headers * add migration notice for v1 to v2 * Update README with v1 and v2 tagged releases * Consistency in response struct fields * remove pointer references for non write/update structs... NOTE: this does not include 'create' structs that already had pointer references on them as I'm unaware of the context related to why they are pointers. * remove pointer references for existing non write/update structs * Compatibool should be non-pointer for 'create' structs * Use pointer reference for Header* constants on write/update structs. * Use pointer reference for PoolType constants on write/update structs. Co-authored-by: oscarDovao <31310209+oscarDovao@users.noreply.github.com> Co-authored-by: Oscar <dovaooj@gmail.com> Co-authored-by: Stuart Wallace <stuart@wapbot.co.uk> Co-authored-by: Patrick Hamann <patrick@fastly.com> Co-authored-by: Mateus Pimenta <1920261+matpimenta@users.noreply.github.com> Co-authored-by: Zsolt Balvanyos <5632209+ZsoltBalvanyos@users.noreply.github.com>
This PR contains a new waf version struct method that checks for emptiness. Empty, in this case, means that non of the configuration fields are populated. This method can be used to prevent sending a back-end server request which will result on an error