Skip to content

Commit 1491673

Browse files
committed
Improved connect arguments to support credentials and SSL mode with SA
- Accept credentials within the HTTP URI - Enable SSL mode using the SQLAlchemy dialect's DB URI
1 parent 3fa42ca commit 1491673

File tree

6 files changed

+62
-2
lines changed

6 files changed

+62
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.venv*
12
.coverage/
23
.idea/
34
.installed.cfg

CHANGES.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ Unreleased
1111
HTTP by default. Previously, this setting defaulted to false. This setting
1212
can be changed via the ``verify_ssl_cert`` connection parameter.
1313

14+
- Adjusted connect arguments to accept credentials within the HTTP URI.
15+
16+
- Adjusted connect arguments to enable SSL mode using the SQLAlchemy dialect's
17+
DB URI.
18+
1419
2020/09/28 0.26.0
1520
=================
1621

src/crate/client/doctests/client.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ also need to provide ``password`` as argument for the ``connect()`` call::
5454
>>> connection = client.connect([crate_host],
5555
... username='me',
5656
... password='my_secret_pw')
57+
>>> connection.client.username
58+
'me'
59+
>>> connection.client.password
60+
'my_secret_pw'
61+
62+
The authentication credentials can also be provided in the URL::
63+
64+
>>> connection = client.connect(['http://me:[email protected]:4200'])
65+
>>> connection.client.username
66+
'me'
67+
>>> connection.client.password
68+
'my_secret_pw'
69+
5770

5871
Default Schema
5972
--------------

src/crate/client/http.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,19 @@ def __init__(self,
346346
servers = [self.default_server]
347347
else:
348348
servers = _to_server_list(servers)
349+
350+
# Try to derive credentials from first server argument if not
351+
# explicitly given.
352+
if not username and not password:
353+
try:
354+
url = urlparse(servers[0])
355+
if url.username is not None:
356+
username = url.username
357+
if url.password is not None:
358+
password = url.password
359+
except Exception:
360+
pass
361+
349362
self._active_servers = servers
350363
self._inactive_servers = []
351364
pool_kw = _pool_kw_args(

src/crate/client/sqlalchemy/dialect.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from sqlalchemy import types as sqltypes
2626
from sqlalchemy.engine import default, reflection
2727
from sqlalchemy.sql import functions
28+
from sqlalchemy.util import asbool
2829

2930
from .compiler import (
3031
CrateCompiler,
@@ -195,6 +196,13 @@ def connect(self, host=None, port=None, *args, **kwargs):
195196
if 'servers' in kwargs:
196197
server = kwargs.pop('servers')
197198
if server:
199+
# Evaluate "ssl" connection URI query parameter.
200+
# TODO: Evaluate more parameters like `ssl_ca`, `ssl_key`, `ssl_cert`,
201+
# `ssl_capath` and `ssl_cipher`.
202+
if "ssl" in kwargs:
203+
use_ssl = asbool(kwargs.pop("ssl"))
204+
if use_ssl:
205+
server = "https://" + server
198206
return self.dbapi.connect(servers=server, **kwargs)
199207
return self.dbapi.connect(**kwargs)
200208

src/crate/client/sqlalchemy/tests/connection_test.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,21 @@ def test_default_connection(self):
3535
self.assertEqual("<Connection <Client ['http://127.0.0.1:4200']>>",
3636
repr(conn.connection))
3737

38-
def test_connection_server(self):
38+
def test_connection_server_uri_http(self):
3939
engine = sa.create_engine(
4040
"crate://otherhost:19201")
4141
conn = engine.raw_connection()
4242
self.assertEqual("<Connection <Client ['http://otherhost:19201']>>",
4343
repr(conn.connection))
4444

45-
def test_connection_multiple_server(self):
45+
def test_connection_server_uri_https(self):
46+
engine = sa.create_engine(
47+
"crate://otherhost:19201/?ssl=true")
48+
conn = engine.raw_connection()
49+
self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
50+
repr(conn.connection))
51+
52+
def test_connection_multiple_server_http(self):
4653
engine = sa.create_engine(
4754
"crate://", connect_args={
4855
'servers': ['localhost:4201', 'localhost:4202']
@@ -53,3 +60,16 @@ def test_connection_multiple_server(self):
5360
"<Connection <Client ['http://localhost:4201', " +
5461
"'http://localhost:4202']>>",
5562
repr(conn.connection))
63+
64+
def test_connection_multiple_server_https(self):
65+
engine = sa.create_engine(
66+
"crate://", connect_args={
67+
'servers': ['https://localhost:4201', 'https://localhost:4202'],
68+
'ssl': True,
69+
}
70+
)
71+
conn = engine.raw_connection()
72+
self.assertEqual(
73+
"<Connection <Client ['https://localhost:4201', " +
74+
"'https://localhost:4202']>>",
75+
repr(conn.connection))

0 commit comments

Comments
 (0)