Skip to content

Refactor RecordConfig: Add getters/setters#314

Merged
tlimoncelli merged 30 commits intomasterfrom
namefqdn
Feb 15, 2018
Merged

Refactor RecordConfig: Add getters/setters#314
tlimoncelli merged 30 commits intomasterfrom
namefqdn

Conversation

@tlimoncelli
Copy link
Copy Markdown
Contributor

No description provided.

@tlimoncelli tlimoncelli changed the title Improve testing: Panic if .Name/.NameFQDN are inconsistent. Refactor RecordConfig: Add getters/setters Feb 1, 2018
@tlimoncelli tlimoncelli requested review from captncraig and removed request for mhenderson-so February 1, 2018 17:18
@tlimoncelli
Copy link
Copy Markdown
Contributor Author

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it would be better to say origin MUST not have a trailing dot.

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.

Done

models/dns.go Outdated

// CheckDomainIntegrity performs sanity checks on a DomainConfig
// and panics if problems are found.
func (dc DomainConfig) CheckDomainIntegrity() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nothing should ever panic. Return an error.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Getters should probably be named GetLabel etc... easier to find stuff in autocomplete.

@captncraig
Copy link
Copy Markdown
Contributor

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.

@tlimoncelli
Copy link
Copy Markdown
Contributor Author

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.

@tlimoncelli
Copy link
Copy Markdown
Contributor Author

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.

@tlimoncelli
Copy link
Copy Markdown
Contributor Author

I'll remove the panic() calls soon.

@tlimoncelli
Copy link
Copy Markdown
Contributor Author

question for @pmoroney:
How does the name.com API expect a TXT record's strings to be encoded/decoded?

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 dnscontrol/providers/namedotcom/records_test.go and see what I'm doing wrong?

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!

@pmoroney
Copy link
Copy Markdown
Contributor

pmoroney commented Feb 4, 2018

I'll take a look right now :)

@pmoroney
Copy link
Copy Markdown
Contributor

pmoroney commented Feb 4, 2018

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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

@tlimoncelli
Copy link
Copy Markdown
Contributor Author

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
@tlimoncelli
Copy link
Copy Markdown
Contributor Author

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) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This name is a little confusing to me. Would SetLabelFromFQDN make a little more sense?

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.

Fixed.

if strings.HasSuffix(origin, ".") {
panic(errors.Errorf("origin (%s) is not supposed to end with a dot", origin))
}
if strings.HasSuffix(fqdn, "..") {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

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.

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 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would SetCAATarget be a more appropriate name? This applies to almost all methods with that pattern.

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.

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))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are all of these variants actually used? I hate dead code, and would rather only add as we need 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 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 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This confuses me, and appears to be unused. Whitelisting might be a better approach than blacklisting if we need to keep it.

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'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()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

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.

Agreed

models/target.go Outdated
}

// GetTargetDebug returns a string with the various fields spelled out.
func (rc *RecordConfig) GetTargetDebug() string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what?

@tlimoncelli tlimoncelli merged commit de44559 into master Feb 15, 2018
@tlimoncelli tlimoncelli deleted the namefqdn branch February 15, 2018 21:10
rblenkinsopp pushed a commit to rblenkinsopp/dnscontrol that referenced this pull request Aug 21, 2020
* 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
tlimoncelli pushed a commit that referenced this pull request Oct 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants