-
Notifications
You must be signed in to change notification settings - Fork 101
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
s/edgeDNSServer/edgeDNSServers/g #605
Conversation
0674e99
to
8886cdd
Compare
Thanks for the early exposure, I've converted it to Draft |
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.
thx for the PR. We shouldn't keep in master untested code or have possibility to start app with invalid inputs.
Please add tests and validations.
@jkremser, I don't see all checks including linter, testrun, terratest etc. Could you make PR from feature branch? |
@kuritka that's kinda of weird - workflows should be executed for all PRs even from the remote forks aren't they? |
yes, that's still on my plate, some tests are still failing, hence the "wip" :) it's a pr from my fork. I like this approach more, because that's how the open-source is done, nobody should assume that people will have write access to this repo, right? I can try to create a feature branch on this repo if it makes any difference |
@kuritka |
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.
@jkremser, please squash commits into one , align PR message with squashed commit.
thx
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.
looks, ok.
Dig
needs to be refactored and must be tested for corner cases. PR affects several parts of k8gb and I didn't have time to go through everything. I will continue with the review tomorrow.
b51ae96
to
d7a9473
Compare
19b12ee
to
fd7b0e9
Compare
@@ -67,8 +86,7 @@ func (dr *DependencyResolver) ResolveOperatorConfig() (*Config, error) { | |||
dr.config.route53Enabled = env.GetEnvAsBoolOrFallback(Route53EnabledKey, false) | |||
dr.config.ns1Enabled = env.GetEnvAsBoolOrFallback(NS1EnabledKey, false) | |||
dr.config.CoreDNSExposed = env.GetEnvAsBoolOrFallback(CoreDNSExposedKey, false) | |||
dr.config.EdgeDNSServer = env.GetEnvAsStringOrFallback(EdgeDNSServerKey, "") | |||
dr.config.EdgeDNSServerPort, _ = env.GetEnvAsIntOrFallback(EdgeDNSServerPortKey, 53) | |||
dr.config.EdgeDNSServers = parseEdgeDNSServers(env.GetEnvAsStringOrFallback(EdgeDNSServersKey, "")) |
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.
We can keep old format and transform it to EdgeDNSServers here (or for clarity, transform before starting the validations)
dr.config.EdgeDNSServers = parseEdgeDNSServers(env.GetEnvAsStringOrFallback(EdgeDNSServersKey, ""))
dr.config.EdgeDNSServer = env.GetEnvAsStringOrFallback(EdgeDNSServerKey, "")
dr.config.EdgeDNSServerPort, _ = env.GetEnvAsIntOrFallback(EdgeDNSServerPortKey, 53)
// Make a transofrmation here (borrowing your comment): old contract, let's transform it to the new api -> will be also validated
^^ consider EdgeDNSServer, EdgeDNSServerPort private until deprecations will be removed (edgeDNSServer, edgeDNSServerPort)
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.
This is actually my initial approach :) that's exactly what I have, but then I was thinking about the log messages for the user and the logger is not being initialized before the config (chicken egg) so I ended up setting the value in the findDeprecations
, but I think you are right and we can use the findDeprecations (or GetDeprecations
) merely for getting the messages and calling it on demand... instead of returning the 3-tuple 👍
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.
actually, not exactly, this is what I have there before:
dr.config.EdgeDNSServers = parseEdgeDNSServers(env.GetEnvAsStringOrFallback(EdgeDNSServersKey,
fmt.Sprintf("%s:%v", env.GetEnvAsStringOrFallback(EdgeDNSServerKey, ""),
env.GetEnvAsStringOrFallback(EdgeDNSServerPortKey, "53"))))
^^ consider EdgeDNSServer, EdgeDNSServerPort private until deprecations will be removed (edgeDNSServer, edgeDNSServerPort)
nah, too messy. The api would be pretty confusing having a plural form, singular form... list of values in one thing, single value in the other... what should be used etc. definitely not going this route, it should be unified to the new version during the validation phase to make our lives easier
func (c *Config) GetExternalClusterNSNames() (m map[string]string) { | ||
m = make(map[string]string, len(c.ExtClustersGeoTags)) | ||
for _, tag := range c.ExtClustersGeoTags { | ||
m[tag] = getNsName(tag, c.DNSZone, c.EdgeDNSZone, c.EdgeDNSServer) | ||
m[tag] = getNsName(tag, c.DNSZone, c.EdgeDNSZone, c.EdgeDNSServers[0].Host) | ||
} | ||
return | ||
} |
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.
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.
EdgeDNS server has no influence on NS name (see this), maybe it would be enough to add validation that would look for EDGE_DNS_SERVERS can be only 127.0.0.1 or localhost, or server list (except 127.0.0.1, localhost)
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.
It would simply pick the first one and never fallback
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.
For now, we should probably not allow the combination {127.0.0.1, host1, host2,....}, we should only allow {127.0.0.1}, or {localhost}; or {host1, host2, host....} . The locahost host should always remain as single element. @jkremser, could you provide validation rule and tests?
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.
edgedns server has a direct influence on NS name resolution. Sticking with only one defeats the idea of multiple edgeDNS Servers to rely on unless I miss something
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.
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.
@jkremser actually i recalled the getNSName
logic, it's fine to evaluate the first one for local scenario. Not sure how it is obvious for external guys though
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've added the check that would fail if localhost or 127.0.0.1 appears on some other position in the list + test called TestResolveConfigWithMultipleEdgeDnsServersLocalhostNotFirst
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.
This may sound a bit nitpicky, but won't there be a difference between what the customer expects and what we will do if he insert the following value ?
EDGE_DNS_SERVERS = "localhost:5053,a.cloud.example.com, b.cloud.example.com"
That's just the reason to stick localhost with single element, or is value above supported?
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.
right, the above example will pass the validation (as I've done it) and I am not sure if it should or should not be supported as a valid use-case. Either way I am not sure how the getNSName
should behave in this case. Perhaps instead of passing the c.EdgeDNSServers[0].Host
to that method, we can pass a boolean called isLocal
or something similar with the intention of not doing the string concat logic in that method, but returning localhost instead... well and that boolean can be calculated as true iff the list contains only 1 element and the element.Host == localhost / 127.0.0.1
wdyt? that way we will still have the fallback mechanism for other methods (Dig, Exchange)
@jkremser , is PR name |
1444d14
to
7a2adfe
Compare
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.
please check my comments,
- depresolver implementation progress well
- consider more EdgeDNSServersKey corner cases and cover by tests.
type oldVar = string | ||
type newVar struct { | ||
Name string | ||
Msg string | ||
} | ||
|
||
var deprecated = map[oldVar]newVar{ | ||
EdgeDNSServerKey: newVar{ | ||
Name: EdgeDNSServersKey, | ||
Msg: "Pass the hostname or IP address as comma-separated list", | ||
}, | ||
EdgeDNSServerPortKey: newVar{ | ||
Name: EdgeDNSServersKey, | ||
Msg: "Port is an optional in the comma-separated list of dns edge servers, in following form: dns1:53,dns2", | ||
}, | ||
} |
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.
Consider optimization:
var deprecated = map[string]string{
EdgeDNSServerKey: "Pass the hostname or IP address as comma-separated list",
EdgeDNSServerPortKey: "Port is an optional in the comma-separated list of dns edge servers, in following form: dns1:53,dns2",
}
Maybe deprecated list doesn't need to be at package level when it is used by only function.
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 didn't want the function to do it over and over again, but I guess that would be my cognitive baggage from my previous job on graalvm compiler (premature optimisation, yada yada..) I've learnt that package scoped vars are evil so I will move that to that function as u suggested because in our case, the function is called only once and even if it's called bazzilion times, I assume the golang compiler can do inlining and escape analysis these days.
As for the suggested new form: I need to also keep track of the "old form" -> "new form" so that user is informed about what is the remedy for the deprecation (check depresolver_config.go:L264
).
dr.config.EdgeDNSServers = parseEdgeDNSServers(env.GetEnvAsStringOrFallback(EdgeDNSServersKey, | ||
fmt.Sprintf("%s:%v", env.GetEnvAsStringOrFallback(EdgeDNSServerKey, ""), | ||
env.GetEnvAsStringOrFallback(EdgeDNSServerPortKey, "53")))) |
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.
Nit: possibly both can be filled EdgeDNSServersKey
and <EdgeDNSServerKey; EdgeDNSServerPortKey
>, but for now looks good.
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.
right, in this case the EdgeDNSServersKey
takes the precedence which is imho reasonable behavior
func (c *Config) GetExternalClusterNSNames() (m map[string]string) { | ||
m = make(map[string]string, len(c.ExtClustersGeoTags)) | ||
for _, tag := range c.ExtClustersGeoTags { | ||
m[tag] = getNsName(tag, c.DNSZone, c.EdgeDNSZone, c.EdgeDNSServer) | ||
m[tag] = getNsName(tag, c.DNSZone, c.EdgeDNSZone, c.EdgeDNSServers[0].Host) | ||
} | ||
return | ||
} |
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.
For now, we should probably not allow the combination {127.0.0.1, host1, host2,....}, we should only allow {127.0.0.1}, or {localhost}; or {host1, host2, host....} . The locahost host should always remain as single element. @jkremser, could you provide validation rule and tests?
6a4c3db
to
8f796ad
Compare
👍 good job @jkremser |
@@ -257,13 +350,13 @@ func parseLogOutputFormat(value string) LogFormat { | |||
func (c *Config) GetExternalClusterNSNames() (m map[string]string) { | |||
m = make(map[string]string, len(c.ExtClustersGeoTags)) | |||
for _, tag := range c.ExtClustersGeoTags { | |||
m[tag] = getNsName(tag, c.DNSZone, c.EdgeDNSZone, c.EdgeDNSServer) | |||
m[tag] = getNsName(tag, c.DNSZone, c.EdgeDNSZone, c.EdgeDNSServers[0].Host) |
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.
What will happen if first ([0]) edge dns server is not accessible?
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.
inside the getNsName()
the dns server is used only in case it's equal to localhost
or 127.0.0.1
(then it's returned -> dummy for tests) otherwise the dns server is ignored and the return value is constructed using EDGE_DNS_ZONE
, geotag and what not.
After the validation it's guaranteed that there will be at least 1 element in that array so c.EdgeDNSServers[0].Host
can't fail.
..is not accessible..
In other words we don't use the dns server here for resolving, instead only the string representation is used in that function. Might be probably done by some mocking + iface for tests but I am not a golang expert :D
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.
@ytsarev , @jkremser - here is the discussion about the topic: #605 (comment)
}, | ||
EdgeDNSServerPortKey: newVar{ | ||
Name: EdgeDNSServersKey, | ||
Msg: "Port is an optional in the comma-separated list of dns edge servers, in following form: dns1:53,dns2", |
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.
does it default to 53
in case of dns2
? if yes, then the message is not totally clear
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.
added better message here and also to values.yaml
@jkremser one last thing, could you please highlight the places in code where we actually increasing reliability with the multiple edgedns servers? https://github.com/k8gb-io/k8gb/pull/605/files#diff-b93d6284f641cd9c665d0167b418250059f2ac5438acf1fe775001c13973a368R295 here and https://github.com/k8gb-io/k8gb/pull/605/files#diff-b93d6284f641cd9c665d0167b418250059f2ac5438acf1fe775001c13973a368R313 here? anywhere else? |
As described in the Issue k8gb-io#154 this adds the ability to fall-back to another edge dns server from the list. These are passed to the operator as env variable `EDGE_DNS_SERVERS` (was singular before) and the value is a comma-separted list of ips/hostnames followed optionally with port number. example: `1.1.1.1:11, 2.2.2.2,hostname` (spaces between entries are supported). Then function `Dig` in `dns.go` has been modified to work with this list (variadic function) and also `Exchange` function in the same file was tweaked to support it. This change doesn't break the backward compatibility, because both `EDGE_DNS_{SERVER,PORT}` still works, but user is notified in the operator logs that these two were deprecated. Some old tests needed to be modified in order to pass and I've added also these new tests: (`in controllers/depresolver/depresolver_test.go`) - TestResolveConfigWithEmptyEdgeDNSServersKey - TestResolveConfigWithMalformedEdgeDNSServersKey - TestResolveConfigWithTwoEdgeDnsServers - TestResolveConfigWithMultipleEdgeDnsServers1 - TestResolveConfigWithMultipleEdgeDnsServers2 - TestResolveConfigWithMultipleEdgeDnsServersMalformed1 - TestResolveConfigWithMultipleEdgeDnsServersMalformed2 - TestResolveConfigWithInvalidEdgeDnsServersValue - TestResolveConfigWithMultipleEdgeDnsServersLocalhostNotFirst (in `controllers/gslb_controller_test.go`) - TestReturnsExternalRecordsUsingFailoverStrategyAndFallbackDNSserver (in `controllers/internal/utils/dns_test.go`) - TestOneValidEdgeDNSInTheList - TestNoValidEdgeDNSInTheList - TestEmptyEdgeDNSInTheList - TestMultipleValidEdgeDNSInTheList - TestEmptyDNSList - TestValidDigFQDNWithDot Signed-off-by: Jirka Kremser <[email protected]>
and that should be it |
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.
Ok, I guess we can merge this epic PR :)
@jkremser impressive job, thanks!
@kuritka thanks a ton for careful review
@jeffhelps it's all your fault man :D
As described in the Issue #154 this adds the ability to fall-back to another edge dns server from the list. These are passed to the operator as env variable
EDGE_DNS_SERVERS
(was singular before) and the value is a comma-separted list of ips/hostnames followed optionally with port number. example:1.1.1.1:11, 2.2.2.2,hostname
(spaces between entries are supported).Then function
Dig
indns.go
has been modified to work with this list (variadic function) and alsoExchange
function in the same file was tweaked to support it.This change doesn't break the backward compatibility, because both
EDGE_DNS_{SERVER,PORT}
still works, but user is notified in the operator logs that these two were deprecated.Some old tests needed to be modified in order to pass and I've added also these new tests:
(
in controllers/depresolver/depresolver_test.go
)(in
controllers/gslb_controller_test.go
)(in
controllers/internal/utils/dns_test.go
)