-
Notifications
You must be signed in to change notification settings - Fork 137
Packet provider #493
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
Packet provider #493
Conversation
|
Hi @deitch. Thanks for your PR. I'm waiting for a kubermatic member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. 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. |
|
/ok-to-test |
|
Fixed formatting issues. |
|
/retest |
|
/retest |
f20ace1 to
ec9d34f
Compare
55a10ed to
0f95c62
Compare
|
/retest |
|
The tests fail btw because of |
Strange that it didn't pick it up locally. Oh well. |
|
/retest |
|
Rebased with correct userdata based on #504 . Restarting packet tests |
|
/test pull-machine-controller-e2e-packet |
|
The tests btw failed because of some gcr issue that broke the kubeadm installation: and |
| c, _, _, err := p.getConfig(machine.Spec.ProviderSpec) | ||
| if err == nil { | ||
| labels["size"] = c.InstanceType | ||
| labels["facilities"] = strings.Join(c.Facilities, ",") |
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.
Not completely happy about this, as it doesn't actually tell the user in which facility the instance ended up being if there was more than one submitted. But I am not sure what a better solution is, as doing an API call every time MachineMetricsLabels gets called is definitely too expensive
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. It is an interesting feature of Packet's API that you can specify one, multiple or "any" facility. See here:
The facilities attribute specifies in what datacenter you wish to create the device.
You can either specify a single facility { "facility": "f1" } , or you can instruct to create the device in the best available datacenter { "facility": "any" }. Additionally it is possible to set a prioritized location selection.
For example { "facility": ["f3", "f2", "any"] } will try to assign to the facility f3, if there are no available f2, and so on. If "any" is not specified for "facility", the request will fail unless it can assign in the selected locations.
When you actually do Create() the device, it returns a device as well. I don't know if that returns the requested facilities or actual facility. I have some go code with a quick experiment to find out.
If it does, could we not just retrieve it, since we save the device at the end of Create()?
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.
Confirmed. The return from the call does tell you what facility it is in, and we save that:
func (p *provider) Create(machine *v1alpha1.Machine, _ *cloud.MachineCreateDeleteData, userdata string) (instance.Instance, error) {
// ...
device, res, err := client.Devices.Create(serverCreateOpts)
// This "device" contains it in `device.Facility.Name`
// ...
// and we return it here
return &packetDevice{device: device}, 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.
Its not that easy, because we would need to store this state somewhere, probably in .Status.ProviderStatus. We can leave that as a follow-up thought.
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.
Makes sense. We do have it, though, so that is a good first step. It is easier to find a place to store something we have, than to find a way to get that which we do not. :-)
| return &packetDevice{device: device}, nil | ||
| } | ||
|
|
||
| return nil, cloudprovidererrors.ErrInstanceNotFound |
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 API can not find the instance it does return an empty error and a nil device...?
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.
Oh, did I get it backwards? Oops. Fixing.
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.
Okay it actually does work, because getDeviceByTag returns a nil error if it can't find the device. I personally find that subpar, because this means all users of p.getPacketDevice must check if the returned device is non-nil (Which they currently don't do). What about making getDeviceByTag return an error if it cant find the device?
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 having a hard time following your logic. I will try to work it through here.
getDeviceByTag()(internal only): gets the device that matches the tag, ornilif none is found. Returns a non-nilerrorif there is a real error.p.getPacketDevice()(internal only): callsgetDeviceByTag(). It really just wrapsgetDeviceByTag()while providing some additional convenience (I probably could subsumegetDeviceByTag()into it, since it no longer is used elsewhere, but I like small, easy-to-understand functions). It returns the device if found,nilif not;erroronly if there was an error.- The internal convenience function
p.getPacketDevice()is consumed byp.Get()andp.MigrateUID(), which check that...
Ah, I see. You are saying that the API from p.getPacketDevice() is "return nil if no device found", but not everyone is respecting that, particularly p.MigrateUID().
OK, that is a bug in my implementation of p.MigrateUID(). I will fix that.
I would like to leave p.getPacketDevice() as is, as I tend to view 3 distinct use cases:
- found the device:
deviceset;err = nil - had a comms or auth error:
device = nil;errset - no error but no matching device:
device = nil;err = 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.
Agree except for no error but no matching device: device = nil; err = nil.. That is counterintuitive, if I get no error I expect the device to be non-nil. Also it makes for redundant nil-checks everywhere p.getPacketDevice is used.
Where in the Hetzner or AWS code do you see a nil error return when no instance was found?
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.
Agree except for no error but no matching device: device = nil; err = nil.. That is counterintuitive, if I get no error I expect the device to be non-nil
To each their own. Since this is internal to the provider, we can agree to disagree.
Where in the Hetzner or AWS code do you see a nil error return when no instance was found?
In MigrateUID() AWS here and Hetzner here
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.
MigrateUID is a special case and only returns a nil error if p.Get returned err == cloudprovidererrors.ErrInstanceNotFound.
This is really prone to result in bugs in the future. Why would I assume that if I call p.getPacketDevice() and err == nil device can also be nil and has to be checked separately?
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.
Like what would you think of a rest api that returned for a GET call a http/200 and no body?
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 would I assume that if I call p.getPacketDevice() and err == nil device can also be nil and has to be checked separately?
That is pretty common, actually.
Like what would you think of a rest api that returned for a GET call a http/200 and no body?
It depends. GET /items/1234 should return a 404 for not found, and a 200 for found. But GET /items or a search like GET /items?name=jim should return 404 only if the path GET /items does not exist. If none matches name=jim, then it should return a 200 with an empty set. That has been a longstanding debate among REST implementers/builders for about as long as Fielding's paper has been out (almost 30 years), but I always came down on that side.
I think, though, that we are spending too much time on this. It is a purely internal private function. It works, is clearly defined. Let's just leave it?
ee23c95 to
aef31e3
Compare
|
Formatting was messed up. I fixed and repushed. |
|
/test pull-machine-controller-e2e-packet |
|
/lgtm so @mrIncompetent can have a look |
mrIncompetent
left a 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.
Nice PR :)
Just a few smaller things and we're ready to merge
|
/lgtm /hold cancel |
|
LGTM label has been added. Git tree hash: 150b8612ee30d68633a2efcfc6d672c6d0219b19
|
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: alvaroaleman, mrIncompetent 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 |
|
/retest |
What this PR does / why we need it:
Add Packet support to the kubermatic machine-controller
Special notes for your reviewer:
Followed the document instructions at here .
I am fairly certain we missed something. Also not sure the easiest way to test it. Would request we do the following: