hcs-core 0.1.282__py3-none-any.whl → 0.1.284__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
hcs_core/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.282"
1
+ __version__ = "0.1.284"
hcs_core/ctxp/_init.py CHANGED
@@ -71,7 +71,7 @@ if _app_name:
71
71
 
72
72
  def app_name():
73
73
  dir_name = path.dirname(state._file._path)
74
- name = dir_name[dir_name.rindex("/") + 1 :]
74
+ name = dir_name[dir_name.rindex(os.sep) + 1 :]
75
75
  if name.startswith("."):
76
76
  return name[1:]
77
77
  raise ValueError("Unable to determine app name: " + dir_name)
hcs_core/ctxp/state.py CHANGED
@@ -31,7 +31,7 @@ class _StateFile:
31
31
  self._cache = jsondot.load(self._path, {}, lock=True)
32
32
  return self._cache
33
33
 
34
- def get(self, key: str, default: Any, reload: bool = False):
34
+ def get(self, key: str, default: Any = None, reload: bool = False):
35
35
  return self._data(reload).get(key, default)
36
36
 
37
37
  def set(self, key: str, value: Any):
@@ -47,7 +47,7 @@ def init(store_path: str, name: str):
47
47
  _file = _StateFile(os.path.join(store_path, name))
48
48
 
49
49
 
50
- def get(key: str, default: Any, reload: bool = False):
50
+ def get(key: str, default: Any = None, reload: bool = False):
51
51
  return _file.get(key=key, default=default, reload=reload)
52
52
 
53
53
 
hcs_core/plan/dag.py CHANGED
@@ -15,6 +15,7 @@ limitations under the License.
15
15
 
16
16
  import threading
17
17
  import time
18
+ import traceback
18
19
  from concurrent.futures import ThreadPoolExecutor
19
20
  from copy import deepcopy
20
21
  from graphlib import TopologicalSorter
hcs_core/sglib/auth.py CHANGED
@@ -16,6 +16,7 @@ limitations under the License.
16
16
  import hashlib
17
17
  import json
18
18
  import logging
19
+ import threading
19
20
  import time
20
21
 
21
22
  import jwt
@@ -59,24 +60,32 @@ def _decode_http_basic_auth_token(basic_token: str):
59
60
  raise CtxpException(f"Invalid basic http auth token: {e}")
60
61
 
61
62
 
63
+ _login_lock = threading.Lock()
64
+
65
+
62
66
  def login(force_refresh: bool = False, panic_on_failure: bool = True):
63
67
  """Ensure login state, using credentials from the current profile. Return oauth token."""
64
- effective_profile = profile.current()
65
-
66
- auth_data = profile.auth.get()
67
- if force_refresh or not _is_auth_valid(auth_data, effective_profile):
68
- oauth_token = _get_new_oauth_token(auth_data.token, effective_profile)
69
- if oauth_token:
70
- use_oauth_token(oauth_token, effective_profile)
71
- elif panic_on_failure:
72
- panic(
73
- "Login failed. If this is configured API key or client credential, refresh the credential from CSP and update profile config. If this is browser based interactive login, login again."
74
- )
68
+
69
+ _login_lock.acquire()
70
+ try:
71
+ effective_profile = profile.current()
72
+
73
+ auth_data = profile.auth.get()
74
+ if force_refresh or not _is_auth_valid(auth_data, effective_profile):
75
+ oauth_token = _get_new_oauth_token(auth_data.token, effective_profile)
76
+ if oauth_token:
77
+ use_oauth_token(oauth_token, effective_profile)
78
+ elif panic_on_failure:
79
+ panic(
80
+ "Login failed. If this is configured API key or client credential, refresh the credential from CSP and update profile config. If this is browser based interactive login, login again."
81
+ )
82
+ else:
83
+ return None
75
84
  else:
76
- return None
77
- else:
78
- oauth_token = auth_data.token
79
- return oauth_token
85
+ oauth_token = auth_data.token
86
+ return oauth_token
87
+ finally:
88
+ _login_lock.release()
80
89
 
81
90
 
82
91
  def _get_new_oauth_token(old_oauth_token, effective_profile):
@@ -100,7 +109,7 @@ def _get_new_oauth_token(old_oauth_token, effective_profile):
100
109
  old_oauth_token = profile.auth.get().token
101
110
  if old_oauth_token:
102
111
  try:
103
- oauth_token = _refresh_oauth_token(old_oauth_token, csp_config.url)
112
+ oauth_token = refresh_oauth_token(old_oauth_token, csp_config.url)
104
113
  except Exception as e:
105
114
  oauth_token = None
106
115
  log.warning(e)
@@ -113,7 +122,7 @@ def _get_new_oauth_token(old_oauth_token, effective_profile):
113
122
  return oauth_token
114
123
 
115
124
 
116
- def _refresh_oauth_token(old_oauth_token: dict, csp_url: str):
125
+ def refresh_oauth_token(old_oauth_token: dict, csp_url: str):
117
126
  with OAuth2Client(token=old_oauth_token) as client:
118
127
  log.debug("Refresh auth token...")
119
128
  new_token = client.refresh_token(csp_url + "/csp/gateway/am/api/auth/token")
@@ -16,6 +16,7 @@ limitations under the License.
16
16
  import json
17
17
  import os
18
18
  import sys
19
+ import threading
19
20
  import time
20
21
  from typing import Callable, Iterator
21
22
 
@@ -27,21 +28,27 @@ from hcs_core.util.query_util import PageRequest, with_query
27
28
 
28
29
  _caches = {}
29
30
 
31
+ _client_instance_lock = threading.RLock()
32
+
30
33
 
31
34
  def hdc_service_client(service_name: str) -> EzClient:
32
- instance = _caches.get(service_name)
33
- if not instance:
34
-
35
- def _get_url(): # make it deferred so no need to initialize profile
36
- url = _get_hcs_url_considering_env_override(service_name)
37
- if not url.endswith("/"):
38
- url += "/"
39
- url += service_name
40
- return url
41
-
42
- instance = hcs_client(_get_url)
43
- _caches[service_name] = instance
44
- return instance
35
+ _client_instance_lock.acquire()
36
+ try:
37
+ instance = _caches.get(service_name)
38
+ if not instance:
39
+
40
+ def _get_url(): # make it deferred so no need to initialize profile
41
+ url = _get_hcs_url_considering_env_override(service_name)
42
+ if not url.endswith("/"):
43
+ url += "/"
44
+ url += service_name
45
+ return url
46
+
47
+ instance = hcs_client(_get_url)
48
+ _caches[service_name] = instance
49
+ return instance
50
+ finally:
51
+ _client_instance_lock.release()
45
52
 
46
53
 
47
54
  def _get_hcs_url_considering_env_override(service_name: str):
@@ -15,7 +15,9 @@ limitations under the License.
15
15
 
16
16
  import json
17
17
  import logging
18
+ import os
18
19
  import sys
20
+ import threading
19
21
  from http.client import HTTPResponse
20
22
  from typing import Callable, Optional, Type, Union
21
23
 
@@ -138,25 +140,30 @@ class EzClient:
138
140
  self._base_url = base_url
139
141
  self._client_impl = oauth_client
140
142
  self._lazy_oauth_client = lazy_oauth_client
143
+ self._lock = threading.Lock()
141
144
 
142
145
  def _client(self):
143
- if not self._client_impl:
144
- client = self._lazy_oauth_client()
145
- base_url = self._base_url() if callable(self._base_url) else self._base_url
146
- client.base_url = base_url
147
- client.timeout = 30
148
- request_hooks = client.event_hooks["request"]
149
- response_hooks = client.event_hooks["response"]
150
- if _log_request not in request_hooks:
151
- request_hooks.append(_log_request)
152
- if _log_response not in response_hooks:
153
- response_hooks.append(_log_response)
154
- if _raise_on_4xx_5xx not in response_hooks:
155
- response_hooks.append(_raise_on_4xx_5xx)
156
- self._client_impl = client
157
-
158
- self._client_impl.ensure_token()
159
- return self._client_impl
146
+ self._lock.acquire()
147
+ try:
148
+ if not self._client_impl:
149
+ client = self._lazy_oauth_client()
150
+ base_url = self._base_url() if callable(self._base_url) else self._base_url
151
+ client.base_url = base_url
152
+ client.timeout = int(os.environ.get("HCS_TIMEOUT", 30))
153
+ request_hooks = client.event_hooks["request"]
154
+ response_hooks = client.event_hooks["response"]
155
+ if _log_request not in request_hooks:
156
+ request_hooks.append(_log_request)
157
+ if _log_response not in response_hooks:
158
+ response_hooks.append(_log_response)
159
+ if _raise_on_4xx_5xx not in response_hooks:
160
+ response_hooks.append(_raise_on_4xx_5xx)
161
+ self._client_impl = client
162
+
163
+ self._client_impl.ensure_token()
164
+ return self._client_impl
165
+ finally:
166
+ self._lock.release()
160
167
 
161
168
  def post(
162
169
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hcs-core
3
- Version: 0.1.282
3
+ Version: 0.1.284
4
4
  Summary: Horizon Cloud Service CLI module.
5
5
  Project-URL: Homepage, https://github.com/euc-eng/hcs-cli
6
6
  Project-URL: Bug Tracker, https://github.com/euc-eng/hcs-cli/issues
@@ -35,7 +35,7 @@ Requires-Dist: schedule>=1.1.0
35
35
  Requires-Dist: setuptools>=70.0.0
36
36
  Requires-Dist: tabulate>=0.9.0
37
37
  Requires-Dist: websocket-client>=1.2.3
38
- Requires-Dist: yumako>=0.1.21
38
+ Requires-Dist: yumako>=0.1.24
39
39
  Provides-Extra: dev
40
40
  Requires-Dist: bandit; extra == 'dev'
41
41
  Requires-Dist: black; extra == 'dev'
@@ -1,6 +1,6 @@
1
- hcs_core/__init__.py,sha256=Jfi46RxCoBJZUyEOPruwtx2aH666Z3W505S836AQ7KM,24
1
+ hcs_core/__init__.py,sha256=cu7zK2WAuHTAQTzBhHUgeqW9691ut6R5zcygIfmPeKc,24
2
2
  hcs_core/ctxp/__init__.py,sha256=bHVHhJP10Luz1a3Kk3zFx14dAO4SY6Q20Lrv8rNWWGc,1075
3
- hcs_core/ctxp/_init.py,sha256=7yFCIJLNp6joUahm58EK2X5OeCKNGM5rmmdPDpZ3Z7o,2794
3
+ hcs_core/ctxp/_init.py,sha256=yq46VOty4zs_WcLt1SrtePxbW8S4RIz4YUCP3xIBvCA,2797
4
4
  hcs_core/ctxp/cli_options.py,sha256=g5JnzOtyWiGLCLcGp5x54MPFLW_NOfhfevXUlX5L8tM,2532
5
5
  hcs_core/ctxp/cli_processor.py,sha256=2RhBz7zFm2UDRwbMDwBpeAQQCt4sjZJzn1nePAcMA_o,7329
6
6
  hcs_core/ctxp/cmd_util.py,sha256=_-VwQSmkfi52qWC3uHQI06mSiIPfsZroDruTDYHXiMA,3119
@@ -17,7 +17,7 @@ hcs_core/ctxp/logger.py,sha256=6Sh1WXUrjrQNU7K6zUlBzE34fIS6o6oMU3eqSknUOEo,6321
17
17
  hcs_core/ctxp/profile.py,sha256=OElbba1V1hnnn-m9UI7-WjUglYpaJ_FHeHjeqyhm13c,7690
18
18
  hcs_core/ctxp/profile_store.py,sha256=v4RvKSaKSJhAt5rEGbC6v-NfaI3N67YffPm-qlrQWdg,1566
19
19
  hcs_core/ctxp/recent.py,sha256=Lbv1q6Ld-7FKFaA_FNyqI_WaFDp9zQAOFjFVzox5GoE,1767
20
- hcs_core/ctxp/state.py,sha256=iXHD_pMfKB2gkK360XfTpJhEcugkH9FlBMO6Rjg4918,1620
20
+ hcs_core/ctxp/state.py,sha256=gjcMRVONKBq7WiFQo-xca1726ngZe90mnPrF3vbXDrU,1634
21
21
  hcs_core/ctxp/task_schd.py,sha256=dKNVUGqv1SSXdHufm552FoLr812Grrj3-CNYmSiCfyw,4648
22
22
  hcs_core/ctxp/template_util.py,sha256=XslvIuRBlTVsUW0Y9M_D8gUPc1jWq6X2p4At2VAe1KU,731
23
23
  hcs_core/ctxp/timeutil.py,sha256=RyRrIRdFHbIghdB8wbC8VdABvc7hki2v51b1x2JvHgo,445
@@ -32,7 +32,7 @@ hcs_core/plan/actions.py,sha256=UvCynzApJUxi39HUoPIQ_uownlbvFbJ4aAs6pmulrLY,125
32
32
  hcs_core/plan/base_provider.py,sha256=CSJFN8lopWTUblw8CW78Epnef9BbJVLhPLk9bPfZceM,1299
33
33
  hcs_core/plan/context.py,sha256=5NI5Otk0jGKtBGvO8Sc1xdOHUCu_lXQYNrSctT3Hyq8,116
34
34
  hcs_core/plan/core.py,sha256=vJDG5WYV6XtYtDjK7lyM6MLrB0OEfH6YDqF06DoC9iw,21137
35
- hcs_core/plan/dag.py,sha256=hZf8nrbh03xY0zfeoKgAZGnkXXpvWgEJwkpOW3ZLYqM,12953
35
+ hcs_core/plan/dag.py,sha256=TDpyXVuiwAxeWwNq2HkeZq8F90CnT97NfAl1NjYcII4,12970
36
36
  hcs_core/plan/helper.py,sha256=__b8tlzLBT1Rm3vgiS-pWnZImaoZbsmKSRJtt_1gj8E,7763
37
37
  hcs_core/plan/kop.py,sha256=G1bOPvvaSqrH_AHWWpGx3sFHNvsulbSu6OnPWgBkOqs,5455
38
38
  hcs_core/plan/provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -41,11 +41,11 @@ hcs_core/plan/provider/dev/_prepare.py,sha256=PvVnheEQwpj8sWYz2lDONQVTs4pHPYuo2c
41
41
  hcs_core/plan/provider/dev/dummy.py,sha256=zKEr9J4WHhlN5gFdmrFyEfCF0xlQlCJg0CC1dG9VaLA,1958
42
42
  hcs_core/plan/provider/dev/fibonacci.py,sha256=8WhDr5c9harNAlVPZomQJEqbWe0hUqbppO6ZkwEUcJ0,1104
43
43
  hcs_core/sglib/__init__.py,sha256=oT0etW7vsEbHlXiGL5x23ZXyyFqeLi81RxQQ5lfKSV0,654
44
- hcs_core/sglib/auth.py,sha256=4NeCVHTzTvTG6JuQqjEr9fsPG_XxMD3tcBvZ5XVRm6s,6048
44
+ hcs_core/sglib/auth.py,sha256=4nYqW4Hl1mOytQRR0uR7MmT_9BOUQW8RwjyPCZcNIQA,6235
45
45
  hcs_core/sglib/cli_options.py,sha256=NvdiHpX_o6IYPEM8cQYLb_R7T4aiXVvYLqn6Vk4Q2-Y,1761
46
- hcs_core/sglib/client_util.py,sha256=77oqjWjy8DB6mKawIyUu7HaHQsQXZRYQB4_v_I7LbZ4,10674
46
+ hcs_core/sglib/client_util.py,sha256=ZCXmNfmUL4_iry4yU2bPWL0dLLNIGu3zp541cFt6Or0,10876
47
47
  hcs_core/sglib/csp.py,sha256=anZqbQLIZw831PgW9Z4pweqfAeBH7rXPIAkwkyPkfGY,8054
48
- hcs_core/sglib/ez_client.py,sha256=ofrwvJPvOMcdsYPrvRaLcGIfEL8s-inKKT1M_gALQAQ,7335
48
+ hcs_core/sglib/ez_client.py,sha256=6R_gnRRxxmJYg6oJTnUB7ZLvUTRlEEYuhRyLLOvMxWI,7592
49
49
  hcs_core/sglib/hcs_client.py,sha256=pxRZQ79ABhOyihAI8oOeTxw2dXkce5-NyRkJAoo0OL0,888
50
50
  hcs_core/sglib/init.py,sha256=w_0ZU70Q1TGbSZsqSi7ewKQqpExFlepOT7mIqH0wnho,310
51
51
  hcs_core/sglib/login_support.py,sha256=9YLhaocomqMLkoXcVW5-iDfS7QW9ON2Btx4OBZMAhaE,7581
@@ -63,6 +63,6 @@ hcs_core/util/query_util.py,sha256=5bh3bUVIQuY9qerndfuyfyzkTExYJ8zD0_e3PSN7y-4,3
63
63
  hcs_core/util/scheduler.py,sha256=bPpCmGUL1UctJMfLPAg-h4Hl2YZr96FiI78-G_Usn08,2958
64
64
  hcs_core/util/ssl_util.py,sha256=MvU102fGwWWh9hhSmLnn1qQIWuD6TjZnN0iH0MXUtW0,1239
65
65
  hcs_core/util/versions.py,sha256=wwbcYFpxBohI-QjcrmxGsNghdnx4EWHBipMUL7vnpwM,1728
66
- hcs_core-0.1.282.dist-info/METADATA,sha256=skrCQy0zO94e9GsawF3UxXpAaPKjbiw5jCgPhg8VRlg,1837
67
- hcs_core-0.1.282.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
68
- hcs_core-0.1.282.dist-info/RECORD,,
66
+ hcs_core-0.1.284.dist-info/METADATA,sha256=CKc4laYZVBkqAVZe4dzprWdYERP-orhakeyfj4B2_DU,1837
67
+ hcs_core-0.1.284.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
68
+ hcs_core-0.1.284.dist-info/RECORD,,