-
Notifications
You must be signed in to change notification settings - Fork 67
Adding the core migrator that rewrites objects of a single resource type #3
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
Conversation
48f6c3e
to
bfff573
Compare
/assign @yliaog for initial review |
/assign @yliaog |
@krzyzacy: GitHub didn't allow me to assign the following users: yliaog. Note that only kubernetes-sigs members and repo collaborators can be assigned. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/assign @yliaog |
It wasn't so much about saving a GET as it was about gaining reliability, readability, and being fully schema agnostic. By using the dynamic client, we're certain that our conversion will work for any type regardless of whether it's known. I'll also note that if we had already split client-go into k8s.io/api specific and generic, we'd prefer to use the dynamic client. This is an infrequently run command, proto versus json isn't hugely important. Now after having written all this, I've realized that the other thing is that if you wire up something to accept proto, you won't be able to easily get namespaces and names and if you aren't carefully it will decode and strip unknown fields. |
@yliaog I intentionally removed all the imports to make review easier. |
pkg/migrator/core.go
Outdated
// creating a working serializer. | ||
// We don't use dynamic client because it only supports json, which | ||
// increases the memory usage of the apiserver. When we support | ||
// migrating CRD or aggregated apis, we need to plumb in a dynamic |
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.
s/plumb/plug/ ?
pkg/migrator/core.go
Outdated
namespaceScoped: namespaceScoped, | ||
client: client, | ||
progress: &dummyProgress{}, | ||
concurrency: 5, |
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.
why hard code it here? if no plan to change it, better make it a const
Agree. With the current typed clients I'll have to worry about version skews. @deads2k, I'm a little bit concerned if the roundtrip of |
return ErrNotRetriable{err} | ||
case errors.IsConflict(err): | ||
return ErrRetriable{err} | ||
case errors.IsServerTimeout(err): |
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 about TooManyRequests? seems to be a retriable
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.
pkg/migrator/core.go
Outdated
if err == nil { | ||
break | ||
} | ||
if canRetry(err) { |
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.
no backoff?
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 backoff if the error suggests "retry after" seconds. General backoff is handled by the RESTClient's built-in rate limiter.
pkg/migrator/core.go
Outdated
for { | ||
list, listError := m.list( | ||
&metav1.ListOptions{ | ||
Limit: 500, |
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.
all const better defined at the beginning of the package
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.
Yes. We are very sure. It decodes to |
pkg/migrator/core.go
Outdated
// TODO: The oc migrator tried to count if the update causes changes. | ||
// To do so it needs to decode the PUT response and extract the | ||
// resourceVersion. | ||
return m.get(namespace, name) |
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 if there is a conflict, this will return what's stored without retry, but it is possible what's stored there is still the old version
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 a bug. I fixed the logic. I'll add unit test when the dynamic client is fixed.
func newPods(num int) []v1.Pod { | ||
var list []v1.Pod | ||
func newPodList(num int) v1.PodList { | ||
var pods []v1.Pod | ||
for i := 0; i < num; i++ { | ||
pod := newPod(fmt.Sprintf("pod%d", i), fmt.Sprintf("namespace%d", i)) |
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 worthwhile to test the nil or empty namespace 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.
Added.
8a0db3c
to
7c075cd
Compare
PTAL @yliaog. Thank you! |
pkg/migrator/core.go
Outdated
|
||
// try tries to migrate the single object by PUT. If the PUT fails due to | ||
// conflicts, the function requests next try to GET the new object. If the GET | ||
// failed, the function requests the next try to GET the new object. |
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.
If the GET failed, and the error is retriable, then it requests next try to GET the new object
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.
Discussed offline. Updated.
/lgtm |
dep doesn't parse the Godeps.json in the dependencies, so this has potential problems. I tried glide as well, it doesn't work out-of-box, and it hasn't been updated since the end of 2017. I'll use dep as long as it works
Let's get this one merged. We can fix issues in later iterations. @yliaog could you re-apply the lgtm? I only added the dependencies after you lgtm'ed it last time. |
/lgtm |
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: caesarxuchao, lavalamp The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/lgtm |
The core migrator lists a chunk of objects, GET&PUT each of them, then continue with the next chunk.
The code more or less resembles the oc admin migrate storage code. A small improvement is that the migrator uses the inconsistent continue token sent by the apiserver in case the original list is compacted. So the migrator doesn't have to finish migrating a resource type in the etcd compaction window (5 mins by default).