koalalorenzo/python-digitalocean

get_data sometimes raises digitalocean.NotFoundError

avollmerhaus opened this issue · 11 comments

I'm trying to move the droplets I create into a specific project so I can keep track of them more easily.
Concept code:

project_name = 'foo'
droplet = digitalocean.Droplet('long list of real params here')

raw_api_manager = digitalocean.baseapi.BaseAPI(token='do_token')
all_projects_do_api_response = raw_api_manager.get_data(url='projects', type='GET')['projects']

for element in all_projects_do_api_response:
    if element['name'] == project_name:
                project_id = element['id']
                break
url = 'projects/{}/resources'.format(project_id)

droplet_id = str(droplet.id)
apidata = {'resources': ['do:droplet:' + droplet_id]}
raw_api_manager.get_data(url=url, type='POST', params=apidata)

This works fine most of the time, but sometimes raw_api_manager.get_data(url='projects', type='GET')['projects'] raises digitalocean.NotFoundError although I'm using the exact same parameters as I did for the successful run a few seconds before.

I get the same issue. Did you find a fix?

Hi! If you find a fix, please submit a PR :)

Unfortunately I did not find a fix and have to admit that I'm not trying to, either. At least not at the moment.
Re-running a few times usually gets the desired result and I'm not using it often.

I'd say this is more related to connection issues. By the code I assume you use provider different that DO? And also by the fact that you can overcome this by retries and issue is very old, I assume it may be closed maybe?

Unfortunately I can't re-test because I don't have access to the DO API at the moment.
But my provider at the time was DO, i used the BaseAPI to be able to move droplets I created into a specific DO "project", at least back then there was no higher-level functionality for this.
I can't entirely rule out network connection problems, but it seems highly unlikely to me because the connection was rock solid otherwise, only this specific function was problematic.

This is also happening to me now ... this was working fine about 10 days ago

pip install -U python-digitalocean
python-digitalocean in /usr/local/lib/python2.7/site-packages (1.15.0)

Using homebrew on Mac, specifically using inside fabric

DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support

Getting a 404 when trying to add or remove droplets to load balancer

import digitalocean
loadBalancerId = 'load-balancer-id'
dropletId = '11111111'
loadBalancer = digitalocean.LoadBalancer(token=token, id=loadBalancerId)
loadBalancer.remove_droplets([dropletId])

@chrisgo I think the 2.7 deprecation message is not related to the library as this should work fine with python 3 (AFAIK). Have you tried with Python 3 instead?

If you find a fix for the 404 error, feel free to send a PR.

Coincidentally I've just come across the add droplets to load balancer problem.

I believe this is because of the trailing slash in LoadBalancer.add_droplets:

"load_balancers/%s/droplets/" % load_balancer.id,

since manually calling:

load_balancer.get_data(
"load_balancers/%s/droplets" % load_balancer.id,
type='POST',
params={"droplet_ids": droplet_ids}
)

works. Similar I guess for remove_droplets, but I've not tried that.

I just had this issue when calling droplet.create() and after some troubleshooting it was because I was passing the vpc by name instead of by ID.

My own fault, the field is called "vpc_uuid", but I have no idea why the API returns a 404:
DEBUG:digitalocean:POST https://api.digitalocean.com/v2/droplets/ data:{'name': 'test', 'size': 's-1vcpu-1gb', 'image': 'redacted', 'region': 'lon1', 'ssh_keys': [redacted], 'backups': False, 'ipv6': False, 'private_networking': True, 'volumes': None, 'tags': ['redacted'], 'monitoring': False, 'vpc_uuid': 'redacted'} {'Content-type': 'application/json', 'Authorization': 'Bearer TOKEN0', 'User-Agent': 'python-digitalocean/1.16.0 requests/2.25.1'} None

DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): api.digitalocean.com:443

DEBUG:urllib3.connectionpool:https://api.digitalocean.com:443 "POST /v2/droplets/ HTTP/1.1" 404 None Traceback (most recent call last): File "/Users/chris/projects/do-api/api-test.py", line 43, in <module> droplet.create() File "/Users/chris/projects/do-api/lib/python3.9/site-packages/digitalocean/Droplet.py", line 568, in create data = self.get_data("droplets/", type=POST, params=data) File "/Users/chris/projects/do-api/lib/python3.9/site-packages/digitalocean/Droplet.py", line 165, in get_data data = super(Droplet, self).get_data(*args, **kwargs) File "/Users/chris/projects/do-api/lib/python3.9/site-packages/digitalocean/baseapi.py", line 222, in get_data raise NotFoundError() digitalocean.NotFoundError

Correcting the VPC to use the UUID instead returned:
DEBUG:digitalocean:POST https://api.digitalocean.com/v2/droplets/ data:{'name': 'redacted', 'size': 's-1vcpu-1gb', 'image': 'redacted', 'region': 'lon1', 'ssh_keys': [redacted], 'backups': False, 'ipv6': False, 'private_networking': True, 'volumes': None, 'tags': ['redacted'], 'monitoring': False, 'vpc_uuid': None} {'Content-type': 'application/json', 'Authorization': 'Bearer TOKEN0', 'User-Agent': 'python-digitalocean/1.16.0 requests/2.25.1'} None

DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): api.digitalocean.com:443

DEBUG:urllib3.connectionpool:https://api.digitalocean.com:443 "POST /v2/droplets/ HTTP/1.1" 202 2041

Just in-case anyone wants to replicate my (crude) troubleshooting I inserted logging.basicConfig(level=logging.DEBUG) into baseapi.py at line 12.

I've found the issue (at least for for me) Digital Ocean do not like trailing '/' at the end of the URL on PUT requests.

I was having an issue where doing a .save() on a loadbalancer was getting a 404. I modified line 271 of LoadBalancers.py from:
return self.get_data("load_balancers/%s/" % self.id,
to
return self.get_data("load_balancers/%s" % self.id,
and it worked.

I don't know how far this fix is needed, as the code base has trailing slashes and non-trailing slashes throughout. I can create a PR for the stuff I can test but this may require feedback from DO about when they do and don't accept a trailing slash as I can't find it in the documentation.

Closing for inactivity