|
1 | 1 | #!/usr/bin/env python |
2 | 2 | """SingleStoreDB Cluster Management.""" |
3 | 3 | import datetime |
| 4 | +import functools |
4 | 5 | import os |
5 | 6 | import re |
6 | 7 | import sys |
7 | 8 | from typing import Any |
| 9 | +from typing import Callable |
8 | 10 | from typing import Dict |
9 | 11 | from typing import List |
10 | 12 | from typing import Optional |
|
31 | 33 | PathLikeABC = os.PathLike[str] |
32 | 34 |
|
33 | 35 |
|
34 | | -def get_token() -> Optional[str]: |
35 | | - """Return the token for the Management API.""" |
36 | | - # See if an API key is configured |
37 | | - tok = get_option('management.token') |
38 | | - if tok: |
39 | | - return tok |
| 36 | +class TTLProperty(object): |
| 37 | + """Property with time limit.""" |
40 | 38 |
|
41 | | - # See if the connection URL contains a JWT |
42 | | - url = get_option('host') |
43 | | - if not url: |
44 | | - return None |
| 39 | + def __init__(self, fget: Callable[[Any], Any], ttl: datetime.timedelta): |
| 40 | + self.fget = fget |
| 41 | + self.ttl = ttl |
| 42 | + self._last_executed = datetime.datetime(2000, 1, 1) |
| 43 | + self._last_result = None |
| 44 | + self.__doc__ = fget.__doc__ |
| 45 | + self._name = '' |
45 | 46 |
|
46 | | - urlp = urlparse(url, scheme='singlestoredb', allow_fragments=True) |
47 | | - if urlp.password: |
48 | | - try: |
49 | | - jwt.decode(urlp.password, options={'verify_signature': False}) |
50 | | - return urlp.password |
51 | | - except jwt.DecodeError: |
52 | | - pass |
| 47 | + def reset(self) -> None: |
| 48 | + self._last_executed = datetime.datetime(2000, 1, 1) |
| 49 | + self._last_result = None |
53 | 50 |
|
54 | | - # Didn't find a key anywhere |
55 | | - return None |
| 51 | + def __set_name__(self, owner: Any, name: str) -> None: |
| 52 | + self._name = name |
56 | 53 |
|
| 54 | + def __get__(self, obj: Any, objtype: Any = None) -> Any: |
| 55 | + if obj is None: |
| 56 | + return self |
57 | 57 |
|
58 | | -def get_organization() -> Optional[str]: |
59 | | - """Return the organization for the current token or environment.""" |
60 | | - org = os.environ.get('SINGLESTOREDB_ORGANIZATION') |
61 | | - if org: |
62 | | - return org |
| 58 | + if self._last_result is not None \ |
| 59 | + and (datetime.datetime.now() - self._last_executed) < self.ttl: |
| 60 | + return self._last_result |
63 | 61 |
|
64 | | - return None |
| 62 | + self._last_result = self.fget(obj) |
| 63 | + self._last_executed = datetime.datetime.now() |
| 64 | + |
| 65 | + return self._last_result |
| 66 | + |
| 67 | + |
| 68 | +def ttl_property(ttl: datetime.timedelta) -> Callable[[Any], Any]: |
| 69 | + """Property with a time-to-live.""" |
| 70 | + def wrapper(func: Callable[[Any], Any]) -> Any: |
| 71 | + out = TTLProperty(func, ttl=ttl) |
| 72 | + return functools.wraps(func)(out) |
| 73 | + return wrapper |
65 | 74 |
|
66 | 75 |
|
67 | 76 | class NamedList(List[T]): |
@@ -107,6 +116,39 @@ def get(self, name_or_id: str, *default: Any) -> Any: |
107 | 116 | raise |
108 | 117 |
|
109 | 118 |
|
| 119 | +def get_token() -> Optional[str]: |
| 120 | + """Return the token for the Management API.""" |
| 121 | + # See if an API key is configured |
| 122 | + tok = get_option('management.token') |
| 123 | + if tok: |
| 124 | + return tok |
| 125 | + |
| 126 | + # See if the connection URL contains a JWT |
| 127 | + url = get_option('host') |
| 128 | + if not url: |
| 129 | + return None |
| 130 | + |
| 131 | + urlp = urlparse(url, scheme='singlestoredb', allow_fragments=True) |
| 132 | + if urlp.password: |
| 133 | + try: |
| 134 | + jwt.decode(urlp.password, options={'verify_signature': False}) |
| 135 | + return urlp.password |
| 136 | + except jwt.DecodeError: |
| 137 | + pass |
| 138 | + |
| 139 | + # Didn't find a key anywhere |
| 140 | + return None |
| 141 | + |
| 142 | + |
| 143 | +def get_organization() -> Optional[str]: |
| 144 | + """Return the organization for the current token or environment.""" |
| 145 | + org = os.environ.get('SINGLESTOREDB_ORGANIZATION') |
| 146 | + if org: |
| 147 | + return org |
| 148 | + |
| 149 | + return None |
| 150 | + |
| 151 | + |
110 | 152 | def enable_http_tracing() -> None: |
111 | 153 | """Enable tracing of HTTP requests.""" |
112 | 154 | import logging |
|
0 commit comments