-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
roachprod, roachtest: use same cluster name sanitization #123961
Conversation
0016299
to
69cc304
Compare
// Unsafe characters are dropped. No length check is performed. | ||
func DNSSafeAccount(account string) string { | ||
func DNSSafeName(name string) string { | ||
safe := func(r rune) rune { | ||
switch { | ||
case r >= 'a' && r <= 'z': | ||
return r | ||
case r >= 'A' && r <= 'Z': | ||
return unicode.ToLower(r) |
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.
Nice! This is indeed more efficient than strings.ToLower
when it's known that the char sequence is ascii. It's essentially inlined to this r += 'a' - 'A'
.
@@ -973,6 +966,9 @@ func (f *clusterFactory) newCluster( | |||
// or a destroy from the previous iteration failed. | |||
return nil, nil, err | |||
} | |||
if errors.HasType(err, (*roachprod.MalformedClusterNameError)(nil)) { |
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.
Let's add a unit test to cover this case.
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 gave it a shot, but I wasn't sure how to feasibly do this without mocking a ton of things. There already is a way to mock cluster creation via TestSpec
+ r.MakeClusterSpec(0)
, but that skips roachprod.Create
and this entire retry loop where we validate the cluster name.
I could mock roachprod.Create
to just return a MalformedclusterNameError
, but I don't think that test would be very useful.
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 could mock roachprod.Create to just return a MalformedclusterNameError, but I don't think that test would be very useful.
That would have been my suggestion as well. I think it would be useful to unit test roachprod.Create
especially in the context of [1]; i.e., ClusterAlreadyExistsError
, MalformedClusterNameError
and potentially future type of errors are non-retryable, so we should be able to cover the fact via a unit test. For now, the mock could randomly return the two non-retryable errors, and we assert that the mock is invoked exactly once, i.e., no retries. Wdyt?
[1] #114523
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.
Done. I was trying to add a case where it didn't error out and that was quite tricky to do without mocking a bunch of things. Mocking the two non-retryable errors cases was simple 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.
Could use a couple of new unit tests (for verifyClusterName
and newCluster
), otherwise looks great!
2d3446b
to
927338d
Compare
pkg/roachprod/roachprod.go
Outdated
|
||
// _findActiveAccounts is a test only variable, used for mocking a provider finding | ||
// active accounts in a unit test, where we don't want to actually access a provider. | ||
var _findActiveAccounts func(l *logger.Logger) (map[string]string, error) |
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.
Is it okay to do this for a package variable? I couldn't think of an easier way to mock vm.FindActiveAccounts
. AFAICT, the tests in a package are run sequentially, so no concurrency in accessing this.
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.
Yep, this is a totally legit. way of mocking which is also used sometimes for dependency injection. E.g., InitTestConnectorFactory
[1] is used to inject (or mock) a test-specific implementation of the KV connector.
However, we could initialize it with the actual implementation, i.e.,
var _findActiveAccounts = vm.FindActiveAccounts
and get rid of the conditional logic below.
[1]
Factory = testConnectorFactory{} |
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.
Done! Thanks for tip
@@ -973,6 +966,9 @@ func (f *clusterFactory) newCluster( | |||
// or a destroy from the previous iteration failed. | |||
return nil, nil, err | |||
} | |||
if errors.HasType(err, (*roachprod.MalformedClusterNameError)(nil)) { |
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 gave it a shot, but I wasn't sure how to feasibly do this without mocking a ton of things. There already is a way to mock cluster creation via TestSpec
+ r.MakeClusterSpec(0)
, but that skips roachprod.Create
and this entire retry loop where we validate the cluster name.
I could mock roachprod.Create
to just return a MalformedclusterNameError
, but I don't think that test would be very useful.
927338d
to
4e09a63
Compare
pkg/roachprod/roachprod.go
Outdated
active, err := vm.FindActiveAccounts(l) | ||
var active map[string]string | ||
var err error | ||
if _findActiveAccounts != nil { |
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.
Can elide this check and just use active, err = _findActiveAccounts(l)
as per above comment.
I am guessing
which creates the missing
|
4e09a63
to
27ab2c2
Compare
Previously, roachtest had it's own function to sanitize cluster names, while roachprod had it's own function to verify cluster names. This change removes both and opts instead to use vm.DNSSafeName. This change also introduces MalformedClusterNameError which gives a hint on what is wrong with the name and tells roachtest not to retry cluster creation.
27ab2c2
to
278679f
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.
LGTM. Thanks for adding the unit tests!
TFTR! bors r=srosenberg |
Build failed: |
🥺 bors retry |
Encountered an error creating backports. Some common things that can go wrong:
You might need to create your backport manually using the backport tool. error creating merge commit from 278679f to blathers/backport-release-24.1-123961: POST https://api.github.com/repos/cockroachdb/cockroach/merges: 409 Merge conflict [] you may need to manually resolve merge conflicts with the backport tool. Backport to branch 24.1.x failed. See errors above. 🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is dev-inf. |
Previously, roachtest had it's own function to sanitize cluster names, while roachprod had it's own function to verify (but not sanitize) cluster names. This change removes both and opts instead to use vm.DNSSafeName.
This change also introduces MalformedClusterNameError which gives a hint on what is wrong with the name and
tells roachtest not to retry cluster creation.
Fixes: #122633
Epic: none
Release note: none