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
Adds ability to define a prefix for etcd paths #5707
Conversation
Looks reasonable at a glance. Thanks for adding the test. @derekwaynecarr, were you interested in reviewing? |
Optimistically assuming "yes" from @derekwaynecarr and assigning; please re-assign if desired, as always. |
fb12eb3
to
616dacc
Compare
I don't know what the problem is with the failed build. I rebased my branch on the upstream master because it became out of date. It builds and passes tests locally. I can't get details by following the "Details" link. Can anyone help? |
I can review |
The Shippable failure is due to shippable not being able to do a docker pull to even run the test. |
Restarted the Shippable build. |
@@ -354,6 +374,17 @@ func (h *EtcdHelper) AtomicUpdate(key string, ptrToType runtime.Object, ignoreNo | |||
} | |||
} | |||
|
|||
// Examines the etcd key and prepends the prefix if it isn't already there. | |||
func (h *EtcdHelper) prefixEtcdKey(key string) string { |
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 am a little confused by this.
Do we pass around fully-qualified keys across methods, or are we always passing around the relative key path?
If I set my prefix to be "/registry/pods", then I would expect every key path in my repository to have that prefix prepended. Instead, this behavior results in saying that my pods will go in "/registry/pods/default", but my services will go in "/registry/pods/registry/services/..." which basically breaks usage of a namespace called "registry" in this example.
In general, I think we should always prefix the key so in my example:
pods: /registry/pods/registry/pods/default/...
services: /registry/pods/registry/services/default/...
Right now, you are basically making the default prefix = "/registry" when you set it as "" as a result.
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.
Good question.
What breaks if this just does the join in the case that the PathPrefix is non-empty?
The use case I imagine is to prefix registry entries with something like "/kubernetes.io/clustername", so pods would be under /kubernetes.io/clustername/registry/pods.
This LGTM aside from the comment on the has prefix check for an edge case. I think if we provide a prefix, it should prefix everything, even if it matches our default internal prefixing. |
7d4ffa1
to
0c3f961
Compare
Patch has been updated as per request. The prefix is now added to all keys unconditionally. |
@@ -155,11 +164,14 @@ func (h *EtcdHelper) ExtractToList(key string, listObj runtime.Object) error { | |||
// a zero object of the requested type, or an error, depending on ignoreNotFound. Treats | |||
// empty responses and nil response nodes exactly like a not found error. | |||
func (h *EtcdHelper) ExtractObj(key string, objPtr runtime.Object, ignoreNotFound bool) error { | |||
key = h.prefixEtcdKey(key) |
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.
So here we prefix the key, and then we pass the prefixed key to h.bodyAndExtractObj and we pass the already prefixed key. The first line in bodyAndExtractObj is to prefix the key again. Doesn't this result in a key with the prefix twice?
This is why I asked if we had a convention in place for passing prefixed or non-prefixed keys across each function so readers can make sense of 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.
We need a test case that works against ExtractObj to validate the behavior here.
I would be more comfortable with this PR if the majority of the test cases set a prefix so I could know we are or are not catching multiple prefixing of a key. Right now, it looks like only one test applies a key, and it does not cover all code paths. |
The testing issue is a good point. One way to ensure that would be to absorb "/registry" into the prefix, and make that the default prefix. Obviously that's a much more invasive change, however. A grep for "/registry" has how many hits OOC? |
OK, the tweaks Ill make:
|
I think there's actually more work here than I thought, and it's complicated by the use of the FakeEtcdClient in the test code. When the test code uses an etcd.REST type to manage keys, then the EtcdHelper gets used (the EtcdHelper is what's responsible for adding the path prefix). However, when the test code uses the FakeEtcdClient to manage keys, then the EtcdHelper is not used and the path prefix is not added. The problem is that usage of them is mixed up in the test code. As an example, the function TestEtcdCreateControllerAlreadyExisting:
I don't fully understand why the FakeEtcdClient is used. I would also say that if there is similar code in production (i.e. code that manages Etcd keys in a way that doesn't use the EtcdHelper, like the FakeEtcdClient does), then this would also put keys into etcd without the prefix. Does it therefore make sense to change the behaviour of the FakeEtcdClient? |
How hard would it be to use EtcdHelper in the tests, as is done here? |
I'm not sure. Are you suggesting replacing the use of FakeEtcdClient with EtcdHelper? |
It needs to be possible to configure mock responses, such as in this example: I haven't looked at it closely enough. Maybe @lavalamp has an idea. Fundamentally, we need something that munges all etcd keys everywhere. |
@@ -30,7 +30,7 @@ func TestGetServersToValidate(t *testing.T) { | |||
config := Config{} | |||
fakeClient := tools.NewFakeEtcdClient(t) | |||
fakeClient.Machines = []string{"http://machine1:4001", "http://machine2", "http://machine3:4003"} | |||
config.EtcdHelper = tools.EtcdHelper{fakeClient, latest.Codec, nil} | |||
config.EtcdHelper = tools.EtcdHelper{fakeClient, latest.Codec, 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.
IMO it's a must to parameterize our tests for this change, like we did with apiversion. That final "" needs to come from a command line flag, and the test-go.sh file should run it with at least "" and "prefix" values.
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 also happens to be a pretty easy thing to do to resolve the testing concerns, fortunately.
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 use testetcd.Prefix()
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.
Use testetcd.PathPrefix() instead of ""; also s/tools.PathPrefix/testetcd.PathPrefix/. Thanks.
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 think you missed this 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.
etcdtest.PathPrefix()
cmd/integration also needs the parameterization. Ideally you'd add a tools/etcd/etcdtest package which defines the flag. |
0c3f961
to
8ce9ab5
Compare
for name, item := range table { | ||
fakeClient, registry := NewTestGenericEtcdRegistry(t) | ||
registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = item.allowCreate | ||
path, _ := registry.KeyFunc(ctx, "foo") | ||
path = etcdtest.AddPrefix(path) |
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.
Same comment-- please fix the other locations too.
Unfortunately I can't finish this review right now-- hopefully this will keep you busy. I definitely feel like we're converging, these requests are all much more minor. Thanks! (PS you're going to have to rebase...) |
bbee135
to
05fb3cf
Compare
Thanks @lavalamp, good to know we're converging. |
05fb3cf
to
a360d31
Compare
@@ -92,7 +92,7 @@ func TestExtractObj(t *testing.T) { | |||
|
|||
func TestWatch(t *testing.T) { | |||
client := newEtcdClient() | |||
helper := tools.NewEtcdHelper(client, testapi.Codec()) | |||
helper := tools.NewEtcdHelper(client, testapi.Codec(), "") |
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.
etcdtest.PathPrefix()
I made another pass. Please note that there are two older comments that I think you haven't noticed. I think this should be the last requests I have. Please fix & rebase and let's get this merged! |
9f32605
to
1ae79bb
Compare
@lavalamp Thanks. I think I've found the two issues you referred and fixed them. |
1ae79bb
to
b27bcf5
Compare
Struggling with a failing integration test at the moment. Having difficulty decoding the error trace - I think it's around the etcd_helper_watch but not sure. Any help would be appreciated. |
hm-- the stuff about not making the kubernetes service is noise-- ignore it.
looks like it might be the relevant part of the stacktrace? |
b27bcf5
to
e2edb4f
Compare
The API server can be supplied (via a command line flag) with a custom prefix that is prepended to etcd resources paths. Refs: kubernetes#3476
e2edb4f
to
a7623ca
Compare
@lavalamp Yes, I fixed the problem you found. However, the integration test fails on the build machine for another reason: https://travis-ci.org/GoogleCloudPlatform/kubernetes/jobs/59856346 The problem is, I can't reproduce it. All the tests on my local machine pass. |
LGTM. Travis is a known flake. Thanks for the change! |
Adds ability to define a prefix for etcd paths
for apiVersion in "${apiVersions[@]}"; do | ||
echo "Running tests for APIVersion: $apiVersion" | ||
KUBE_API_VERSION="${apiVersion}" runTests "$@" | ||
KUBE_API_VERSION="${apiVersion}" ETCD_PREFIX=${ETCD_STANDARD_PREFIX} runTests "$@" |
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.
Locally, unit tests are now being run 3 times!
For v1beta1, beta3 and etcdPrefix.
@bgrant0607 @lavalamp
Is this intended?
Maybe we can run with v1beta1 and standard prefix once and then v1beta3 and custom prefix (or vice-versa)?
Or if the test passes with a custom prefix, then it means that it will pass with the standard prefix as well?
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.
Yes, this was intentional-- I don't mind if you combine the runs like you suggest, but we do need to test at least once with a custom prefix.
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.
Its actually running 4 times on shippable and travis :)
Twice with go 1.3 (v1beta1 and then custom etcdPrefix)
and twice with go 1.4 (v1beta3 and custom etcdPrefix)
Sending a PR to fix 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.
Being fixed in #8134
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.
Thanks. I'd eventually like to get back to no extra test runs for this.
Yes, we already have enough problems with test bandwidth. |
The API server can be supplied (via a command line flag) with a custom
prefix that is prepended to etcd resources paths.
Refs: #3476