Refactor RecordConfig: Add getters/setters#314
Conversation
|
I set up getters/setters for .Name and .Target and split the functions to their own file. What do you think about their names? |
models/record.go
Outdated
| // This is | ||
|
|
||
| // SetLabel sets the .Name/.NameFQDN fields given a short name and origin. | ||
| // origin may not have a trailing dot. |
There was a problem hiding this comment.
I think it would be better to say origin MUST not have a trailing dot.
models/dns.go
Outdated
|
|
||
| // CheckDomainIntegrity performs sanity checks on a DomainConfig | ||
| // and panics if problems are found. | ||
| func (dc DomainConfig) CheckDomainIntegrity() { |
There was a problem hiding this comment.
Nothing should ever panic. Return an error.
There was a problem hiding this comment.
Should more of the normalize package be moved into models or vice versa? There are some poorly defined package boundaries here.
models/dns.go
Outdated
| } | ||
|
|
||
| // checkNameFQDN panics if there is a Name/NameFQDN mismatch. | ||
| func checkNameFQDN(recs []*RecordConfig, origin string) { |
There was a problem hiding this comment.
this needa a better name
models/record.go
Outdated
| Target string `json:"target"` // If a name, must end with "." | ||
| TTL uint32 `json:"ttl,omitempty"` | ||
| Metadata map[string]string `json:"meta,omitempty"` | ||
| NameFQDN string `json:"-"` // Must end with ".$origin". See above. |
There was a problem hiding this comment.
If Record kept a pointer to its' parent domain, maybe GetNameFQDN could just be a pure function, so we don't even need to store fqdn seperately at all? Just the short name. Would be a larger change to break each provider, but compiler would help us out.
models/record.go
Outdated
| // It does not need further shortening (i.e. if it returns "foo.com" and the | ||
| // domain is "foo.com" then the FQDN is actually "foo.com.foo.com"). | ||
| // It will never be "" (the apex is returned as "@"). | ||
| func (rc *RecordConfig) Label() string { |
There was a problem hiding this comment.
Getters should probably be named GetLabel etc... easier to find stuff in autocomplete.
|
I have a few concerns about naming conventions and some of the specifics of how it works. Its kinda hard to put precicely what those are into clear words though. I think it is a step in the right direction to try and enforce conventions at some higher level than each provider deciding their own way of representing things. I made some initial comments. Only got through some of the files though. Will continue a deeper review later tonight. |
|
I renamed Label* to GetLabel* as suggested. I converted a few more providers, which was very educational and I found a few ways to improve the functions. I agree that the checkIntegrity stuff should be moved. Let's do another PR later that refactors the normalization/validation stuff. I think you'll be happy with one recent change: You know how every "switch rtype" tends to have a default clause that calls panic()? Well, now the default can just call rc.PopulateFromString() and it handles most situations. In fact, move nativeToRecord() methods now only need to handle a few types (the ones that they handle in a non-standard way) then call rc.PopulateFromString(). Done. |
|
MergeToTarget() This is now eliminated in all providers with official support. I could remove it from dnsimple but I don't have a test account. Do you? RecordConfig.Content() is now unexported. This found a lot of bad behavior. RecordConfig.CombinedTarget has been eliminated from all official providers. I need a test account for ovh and ns1 to be able to completely eliminate it. Once PopulateFromString() was written, converting providers became a lot easier. |
|
I'll remove the panic() calls soon. |
|
question for @pmoroney: More specifically: In the name.com API, when a TXT record has multiple strings, it looks like we send (or receive) them all in r.Answer as one big string. However, it isn't documented how that string is to be encoded (or decoded). Could I ask you a favor and request that you look at Oddly enough the code in the master branch works fine. The code in this branch looks exactly the same. I can't figure out how I broke it. Maybe I just haven't moved the code over properly or the test cases are wrong. (I admit I get the \ escaping and quoting mixed up some times). Any help would be greatly appreciated! |
|
I'll take a look right now :) |
|
Since I don't have access to push to this branch, I created a pull request here: #315 |
models/record.go
Outdated
| // Official: | ||
| // A | ||
| // AAAA | ||
| // ANAME |
There was a problem hiding this comment.
ANAME is still just a draft and I don't think any providers support it outright.
Name.com's ANAME record is really just an ALIAS until there is more support for the real ANAME draft.
|
Once we fix ovh, we're ready to remove the RecordConfig.CombinedTarget field and the CombineMXs() function. At that point, we can consider unexporting .Name/.NameFQDN/.Target. |
* Replace fmt.Errorf with errors.Errorf * Finish removing CombinedTarget
|
Finished with global changes for now. NOTE TO SELF: Merge everything but the community providers, then create a PR for each provider for each maintainer to approve. |
models/record.go
Outdated
| // SetLabelFQDN sets the .Name/.NameFQDN fields given a FQDN and origin. | ||
| // fqdn may have a trailing "." but it is not required. | ||
| // origin may not have a trailing dot. | ||
| func (rc *RecordConfig) SetLabelFQDN(fqdn, origin string) { |
There was a problem hiding this comment.
This name is a little confusing to me. Would SetLabelFromFQDN make a little more sense?
| if strings.HasSuffix(origin, ".") { | ||
| panic(errors.Errorf("origin (%s) is not supposed to end with a dot", origin)) | ||
| } | ||
| if strings.HasSuffix(fqdn, "..") { |
There was a problem hiding this comment.
There is a point where the user is just trying to shoot themselves in the foot. We don't check double dots in the middle for example.
I feel like we should either do more rigorous validation here ((\w+\.)+ maybe), or test fewer things.
In the future, I think maybe the validation package being separate is a mistake and we should just have a single call Validate on dnsconfig that cascades down to domains and records.
There was a problem hiding this comment.
The panics are only for assertions failures. i.e. the code is being used wrong. I could change them to errors later, but these are literally "this should never happen" panics.
As far as validation... yes, that needs to be refactored some day.
| ) | ||
|
|
||
| // SetTargetCAA sets the CAA fields. | ||
| func (rc *RecordConfig) SetTargetCAA(flag uint8, tag string, target string) error { |
There was a problem hiding this comment.
Would SetCAATarget be a more appropriate name? This applies to almost all methods with that pattern.
There was a problem hiding this comment.
It is more searchable to have SetTarget*
| // } | ||
| func (r *RecordConfig) PopulateFromString(rtype, contents, origin string) error { | ||
| if r.Type != "" && r.Type != rtype { | ||
| panic(errors.Errorf("assertion failed: rtype already set (%s) (%s)", rtype, r.Type)) |
There was a problem hiding this comment.
I'm even more confused by panic here. We return an error, but also panic sometimes? What is going on?
| ) | ||
|
|
||
| // SetTargetSRV sets the SRV fields. | ||
| func (rc *RecordConfig) SetTargetSRV(priority, weight, port uint16, target string) error { |
There was a problem hiding this comment.
Are all of these variants actually used? I hate dead code, and would rather only add as we need to.
There was a problem hiding this comment.
I commented out all the SetTarget$RTYPE functions and only brought back the ones that are in use. They're all in use :-)
models/target.go
Outdated
|
|
||
| // GetTargetSingle returns the target for types that have a single value target | ||
| // and panics for all others. | ||
| func (rc *RecordConfig) GetTargetSingle() string { |
There was a problem hiding this comment.
This confuses me, and appears to be unused. Whitelisting might be a better approach than blacklisting if we need to keep it.
There was a problem hiding this comment.
I've commented out a lot of these functions and only brought back the ones that are in use.
| // Sadly String() always includes a header, which we must strip out. | ||
| // TODO(tlim): Request the dns project add a function that returns | ||
| // the string without the header. | ||
| rr := rc.ToRR() |
There was a problem hiding this comment.
Ug. If we are cheating by converting to RR, maybe we should bite the bullet and use RR as our internal representation. Or some type that embeds or encapsulates an RR for metadata and stuff. And maybe some additional implementations for custom stuff.
Getting kinda frustrated at the complexity we've built to avoid it.
models/target.go
Outdated
| } | ||
|
|
||
| // GetTargetDebug returns a string with the various fields spelled out. | ||
| func (rc *RecordConfig) GetTargetDebug() string { |
There was a problem hiding this comment.
Not sure about leaving debug code in.
| } | ||
|
|
||
| // atou32 converts a string to uint32 or panics. | ||
| // DEPRECATED: This will go away when SOA record handling is rewritten. |
* Replace RecordConfig.Name and .NameFQDN with getters and setters. * Replace RecordConfig.Target with getters and setters. * Eliminate the CombinedTarget concept. * Add RecordConfig.PopulateFromString to reduce code in all providers. * encode and decode name.com txt records (StackExchange#315) * Replace fmt.Errorf with errors.Errorf
No description provided.