It's preventing me from using dask-kubernetes, unfortunately.
I'll post the full traceback below.
I validated with kr8s v0.8.18 and the tip of main.
Here's what my kube config looks like (sanitized) in case the presence or lack thereof of specific keys is helpful:
SSLCertVerificationError Traceback (most recent call last)
/Users/obfuscated/code/obfuscated/obfuscated/ignore/lab.ipynb Cell 3 line 3
1 import kr8s
----> 3 pods = kr8s.get("pods")
4 print(pods)
File ~/code/kr8s/kr8s/_io.py:46, in run_sync.<locals>.wrapped(*args, **kwargs)
44 with anyio.from_thread.start_blocking_portal() as portal:
45 if inspect.iscoroutinefunction(coro):
---> 46 return portal.call(wrapped)
47 if inspect.isasyncgenfunction(coro):
48 return iter_over_async(wrapped)
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/anyio/from_thread.py:277, in BlockingPortal.call(self, func, *args)
264 def call(
265 self, func: Callable[..., Awaitable[T_Retval] | T_Retval], *args: object
266 ) -> T_Retval:
267 """
268 Call the given function in the event loop thread.
269
(...)
275
276 """
--> 277 return cast(T_Retval, self.start_task_soon(func, *args).result())
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/concurrent/futures/_base.py:446, in Future.result(self, timeout)
444 raise CancelledError()
445 elif self._state == FINISHED:
--> 446 return self.__get_result()
447 else:
448 raise TimeoutError()
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/concurrent/futures/_base.py:391, in Future.__get_result(self)
389 if self._exception:
390 try:
--> 391 raise self._exception
392 finally:
393 # Break a reference cycle with the exception in self._exception
394 self = None
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/anyio/from_thread.py:217, in BlockingPortal._call_func(self, func, args, kwargs, future)
214 else:
215 future.add_done_callback(callback)
--> 217 retval = await retval
218 except self._cancelled_exc_class:
219 future.cancel()
File ~/code/kr8s/kr8s/asyncio/_helpers.py:23, in get(kind, namespace, label_selector, field_selector, as_object, api, _asyncio, *names, **kwargs)
21 if api is None:
22 api = await _api(_asyncio=_asyncio)
---> 23 return await api._get(
24 kind,
25 *names,
26 namespace=namespace,
27 label_selector=label_selector,
28 field_selector=field_selector,
29 as_object=as_object,
30 **kwargs,
31 )
File ~/code/kr8s/kr8s/_api.py:332, in Api._get(self, kind, namespace, label_selector, field_selector, as_object, *names, **kwargs)
328 group, version = as_object.version.split("/")
329 headers[
330 "Accept"
331 ] = f"application/json;as={as_object.kind};v={version};g={group}"
--> 332 async with self._get_kind(
333 kind,
334 namespace=namespace,
335 label_selector=label_selector,
336 field_selector=field_selector,
337 headers=headers or None,
338 **kwargs,
339 ) as (obj_cls, response):
340 resourcelist = response.json()
341 if (
342 as_object
343 and "kind" in resourcelist
344 and resourcelist["kind"] == as_object.kind
345 ):
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/contextlib.py:181, in _AsyncGeneratorContextManager.__aenter__(self)
179 del self.args, self.kwds, self.func
180 try:
--> 181 return await self.gen.__anext__()
182 except StopAsyncIteration:
183 raise RuntimeError("generator didn't yield") from None
File ~/code/kr8s/kr8s/_api.py:261, in Api._get_kind(self, kind, namespace, label_selector, field_selector, params, watch, **kwargs)
259 params = params or None
260 obj_cls = get_class(kind, _asyncio=self._asyncio)
--> 261 async with self.call_api(
262 method="GET",
263 url=kind,
264 version=obj_cls.version,
265 namespace=namespace if obj_cls.namespaced else None,
266 params=params,
267 **kwargs,
268 ) as response:
269 yield obj_cls, response
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/contextlib.py:181, in _AsyncGeneratorContextManager.__aenter__(self)
179 del self.args, self.kwds, self.func
180 try:
--> 181 return await self.gen.__anext__()
182 except StopAsyncIteration:
183 raise RuntimeError("generator didn't yield") from None
File ~/code/kr8s/kr8s/_api.py:132, in Api.call_api(self, method, version, base, namespace, url, raise_for_status, stream, **kwargs)
130 yield response
131 else:
--> 132 response = await self._session.request(**kwargs)
133 if raise_for_status:
134 response.raise_for_status()
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpx/_client.py:1530, in AsyncClient.request(self, method, url, content, data, files, json, params, headers, cookies, auth, follow_redirects, timeout, extensions)
1501 """
1502 Build and send a request.
1503
(...)
1515 [0]: /advanced/#merging-of-configuration
1516 """
1517 request = self.build_request(
1518 method=method,
1519 url=url,
(...)
1528 extensions=extensions,
1529 )
-> 1530 return await self.send(request, auth=auth, follow_redirects=follow_redirects)
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpx/_client.py:1617, in AsyncClient.send(self, request, stream, auth, follow_redirects)
1609 follow_redirects = (
1610 self.follow_redirects
1611 if isinstance(follow_redirects, UseClientDefault)
1612 else follow_redirects
1613 )
1615 auth = self._build_request_auth(request, auth)
-> 1617 response = await self._send_handling_auth(
1618 request,
1619 auth=auth,
1620 follow_redirects=follow_redirects,
1621 history=[],
1622 )
1623 try:
1624 if not stream:
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpx/_client.py:1645, in AsyncClient._send_handling_auth(self, request, auth, follow_redirects, history)
1642 request = await auth_flow.__anext__()
1644 while True:
-> 1645 response = await self._send_handling_redirects(
1646 request,
1647 follow_redirects=follow_redirects,
1648 history=history,
1649 )
1650 try:
1651 try:
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpx/_client.py:1682, in AsyncClient._send_handling_redirects(self, request, follow_redirects, history)
1679 for hook in self._event_hooks["request"]:
1680 await hook(request)
-> 1682 response = await self._send_single_request(request)
1683 try:
1684 for hook in self._event_hooks["response"]:
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpx/_client.py:1719, in AsyncClient._send_single_request(self, request)
1714 raise RuntimeError(
1715 "Attempted to send an sync request with an AsyncClient instance."
1716 )
1718 with request_context(request=request):
-> 1719 response = await transport.handle_async_request(request)
1721 assert isinstance(response.stream, AsyncByteStream)
1722 response.request = request
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpx/_transports/default.py:353, in AsyncHTTPTransport.handle_async_request(self, request)
340 req = httpcore.Request(
341 method=request.method,
342 url=httpcore.URL(
(...)
350 extensions=request.extensions,
351 )
352 with map_httpcore_exceptions():
--> 353 resp = await self._pool.handle_async_request(req)
355 assert isinstance(resp.stream, typing.AsyncIterable)
357 return Response(
358 status_code=resp.status,
359 headers=resp.headers,
360 stream=AsyncResponseStream(resp.stream),
361 extensions=resp.extensions,
362 )
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpcore/_async/connection_pool.py:262, in AsyncConnectionPool.handle_async_request(self, request)
260 with AsyncShieldCancellation():
261 await self.response_closed(status)
--> 262 raise exc
263 else:
264 break
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpcore/_async/connection_pool.py:245, in AsyncConnectionPool.handle_async_request(self, request)
242 raise exc
244 try:
--> 245 response = await connection.handle_async_request(request)
246 except ConnectionNotAvailable:
247 # The ConnectionNotAvailable exception is a special case, that
248 # indicates we need to retry the request on a new connection.
(...)
252 # might end up as an HTTP/2 connection, but which actually ends
253 # up as HTTP/1.1.
254 async with self._pool_lock:
255 # Maintain our position in the request queue, but reset the
256 # status so that the request becomes queued again.
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpcore/_async/http_proxy.py:299, in AsyncTunnelHTTPConnection.handle_async_request(self, request)
293 kwargs = {
294 "ssl_context": ssl_context,
295 "server_hostname": self._remote_origin.host.decode("ascii"),
296 "timeout": timeout,
297 }
298 async with Trace("start_tls", logger, request, kwargs) as trace:
--> 299 stream = await stream.start_tls(**kwargs)
300 trace.return_value = stream
302 # Determine if we should be using HTTP/1.1 or HTTP/2
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpcore/_backends/anyio.py:78, in AnyIOStream.start_tls(self, ssl_context, server_hostname, timeout)
76 except Exception as exc: # pragma: nocover
77 await self.aclose()
---> 78 raise exc
79 return AnyIOStream(ssl_stream)
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/httpcore/_backends/anyio.py:69, in AnyIOStream.start_tls(self, ssl_context, server_hostname, timeout)
67 try:
68 with anyio.fail_after(timeout):
---> 69 ssl_stream = await anyio.streams.tls.TLSStream.wrap(
70 self._stream,
71 ssl_context=ssl_context,
72 hostname=server_hostname,
73 standard_compatible=False,
74 server_side=False,
75 )
76 except Exception as exc: # pragma: nocover
77 await self.aclose()
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/anyio/streams/tls.py:123, in TLSStream.wrap(cls, transport_stream, server_side, hostname, ssl_context, standard_compatible)
113 ssl_object = ssl_context.wrap_bio(
114 bio_in, bio_out, server_side=server_side, server_hostname=hostname
115 )
116 wrapper = cls(
117 transport_stream=transport_stream,
118 standard_compatible=standard_compatible,
(...)
121 _write_bio=bio_out,
122 )
--> 123 await wrapper._call_sslobject_method(ssl_object.do_handshake)
124 return wrapper
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/site-packages/anyio/streams/tls.py:131, in TLSStream._call_sslobject_method(self, func, *args)
129 while True:
130 try:
--> 131 result = func(*args)
132 except ssl.SSLWantReadError:
133 try:
134 # Flush any pending writes first
File /opt/homebrew/Caskroom/miniconda/base/envs/3.9/lib/python3.9/ssl.py:945, in SSLObject.do_handshake(self)
943 def do_handshake(self):
944 """Start the SSL/TLS handshake."""
--> 945 self._sslobj.do_handshake()
SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1129)