teradataml 20.0.0.4__py3-none-any.whl → 20.0.0.6__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.
Potentially problematic release.
This version of teradataml might be problematic. Click here for more details.
- teradataml/LICENSE-3RD-PARTY.pdf +0 -0
- teradataml/README.md +182 -13
- teradataml/__init__.py +2 -1
- teradataml/_version.py +2 -2
- teradataml/analytics/analytic_function_executor.py +8 -13
- teradataml/analytics/json_parser/analytic_functions_argument.py +4 -0
- teradataml/analytics/sqle/__init__.py +16 -1
- teradataml/analytics/utils.py +60 -1
- teradataml/automl/__init__.py +290 -106
- teradataml/automl/autodataprep/__init__.py +471 -0
- teradataml/automl/data_preparation.py +29 -10
- teradataml/automl/data_transformation.py +11 -0
- teradataml/automl/feature_engineering.py +64 -4
- teradataml/automl/feature_exploration.py +639 -25
- teradataml/automl/model_training.py +1 -1
- teradataml/clients/auth_client.py +12 -8
- teradataml/clients/keycloak_client.py +165 -0
- teradataml/common/constants.py +71 -26
- teradataml/common/exceptions.py +32 -0
- teradataml/common/messagecodes.py +28 -0
- teradataml/common/messages.py +13 -4
- teradataml/common/sqlbundle.py +3 -2
- teradataml/common/utils.py +345 -45
- teradataml/context/context.py +259 -93
- teradataml/data/apriori_example.json +22 -0
- teradataml/data/docs/sqle/docs_17_20/Apriori.py +138 -0
- teradataml/data/docs/sqle/docs_17_20/NERExtractor.py +121 -0
- teradataml/data/docs/sqle/docs_17_20/NGramSplitter.py +3 -3
- teradataml/data/docs/sqle/docs_17_20/SMOTE.py +212 -0
- teradataml/data/docs/sqle/docs_17_20/TextMorph.py +119 -0
- teradataml/data/docs/sqle/docs_17_20/TextParser.py +54 -3
- teradataml/data/docs/uaf/docs_17_20/ACF.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/ArimaEstimate.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/ArimaXEstimate.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/DFFT.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/DFFT2.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/DFFT2Conv.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/DFFTConv.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/FilterFactory1d.py +4 -4
- teradataml/data/docs/uaf/docs_17_20/GenseriesSinusoids.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/GoldfeldQuandt.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/HoltWintersForecaster.py +6 -6
- teradataml/data/docs/uaf/docs_17_20/LineSpec.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/LinearRegr.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/Matrix2Image.py +4 -4
- teradataml/data/docs/uaf/docs_17_20/MultivarRegr.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/PACF.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/PowerSpec.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/PowerTransform.py +3 -3
- teradataml/data/docs/uaf/docs_17_20/Resample.py +5 -5
- teradataml/data/docs/uaf/docs_17_20/SAX.py +3 -3
- teradataml/data/docs/uaf/docs_17_20/SignifPeriodicities.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/SimpleExp.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/Smoothma.py +3 -3
- teradataml/data/docs/uaf/docs_17_20/UNDIFF.py +1 -1
- teradataml/data/jsons/byom/onnxembeddings.json +1 -0
- teradataml/data/jsons/sqle/17.20/NGramSplitter.json +6 -6
- teradataml/data/jsons/sqle/17.20/TD_Apriori.json +181 -0
- teradataml/data/jsons/sqle/17.20/TD_NERExtractor.json +145 -0
- teradataml/data/jsons/sqle/17.20/TD_SMOTE.json +267 -0
- teradataml/data/jsons/sqle/17.20/TD_TextMorph.json +134 -0
- teradataml/data/jsons/sqle/17.20/TD_TextParser.json +114 -9
- teradataml/data/jsons/sqle/20.00/AI_AnalyzeSentiment.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_AskLLM.json +420 -0
- teradataml/data/jsons/sqle/20.00/AI_DetectLanguage.json +343 -0
- teradataml/data/jsons/sqle/20.00/AI_ExtractKeyPhrases.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_MaskPII.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_RecognizeEntities.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_RecognizePIIEntities.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_TextClassifier.json +359 -0
- teradataml/data/jsons/sqle/20.00/AI_TextEmbeddings.json +360 -0
- teradataml/data/jsons/sqle/20.00/AI_TextSummarize.json +343 -0
- teradataml/data/jsons/sqle/20.00/AI_TextTranslate.json +343 -0
- teradataml/data/jsons/sqle/20.00/TD_SMOTE.json +2 -2
- teradataml/data/jsons/sqle/20.00/TD_VectorDistance.json +1 -1
- teradataml/data/ner_dict.csv +8 -0
- teradataml/data/ner_input_eng.csv +7 -0
- teradataml/data/ner_rule.csv +5 -0
- teradataml/data/pattern_matching_data.csv +11 -0
- teradataml/data/pos_input.csv +40 -0
- teradataml/data/sdk/modelops/modelops_spec.json +101737 -0
- teradataml/data/tdnerextractor_example.json +14 -0
- teradataml/data/teradataml_example.json +21 -1
- teradataml/data/textmorph_example.json +5 -0
- teradataml/data/to_num_data.csv +4 -0
- teradataml/data/tochar_data.csv +5 -0
- teradataml/data/trans_dense.csv +16 -0
- teradataml/data/trans_sparse.csv +55 -0
- teradataml/data/url_data.csv +10 -9
- teradataml/dataframe/copy_to.py +38 -27
- teradataml/dataframe/data_transfer.py +61 -45
- teradataml/dataframe/dataframe.py +1110 -132
- teradataml/dataframe/dataframe_utils.py +73 -27
- teradataml/dataframe/functions.py +1070 -9
- teradataml/dataframe/sql.py +750 -959
- teradataml/dbutils/dbutils.py +33 -13
- teradataml/dbutils/filemgr.py +14 -10
- teradataml/hyperparameter_tuner/utils.py +4 -2
- teradataml/lib/aed_0_1.dll +0 -0
- teradataml/opensource/_base.py +12 -157
- teradataml/options/configure.py +24 -9
- teradataml/scriptmgmt/UserEnv.py +317 -39
- teradataml/scriptmgmt/lls_utils.py +456 -135
- teradataml/sdk/README.md +79 -0
- teradataml/sdk/__init__.py +4 -0
- teradataml/sdk/_auth_modes.py +422 -0
- teradataml/sdk/_func_params.py +487 -0
- teradataml/sdk/_json_parser.py +453 -0
- teradataml/sdk/_openapi_spec_constants.py +249 -0
- teradataml/sdk/_utils.py +236 -0
- teradataml/sdk/api_client.py +897 -0
- teradataml/sdk/constants.py +62 -0
- teradataml/sdk/modelops/__init__.py +98 -0
- teradataml/sdk/modelops/_client.py +406 -0
- teradataml/sdk/modelops/_constants.py +304 -0
- teradataml/sdk/modelops/models.py +2308 -0
- teradataml/sdk/spinner.py +107 -0
- teradataml/store/__init__.py +1 -1
- teradataml/table_operators/Apply.py +16 -1
- teradataml/table_operators/Script.py +20 -1
- teradataml/table_operators/query_generator.py +4 -21
- teradataml/table_operators/table_operator_util.py +58 -9
- teradataml/utils/dtypes.py +4 -2
- teradataml/utils/internal_buffer.py +22 -2
- teradataml/utils/utils.py +0 -1
- teradataml/utils/validators.py +318 -58
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/METADATA +188 -14
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/RECORD +131 -84
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/WHEEL +0 -0
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/top_level.txt +0 -0
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/zip-safe +0 -0
|
@@ -10,36 +10,38 @@ teradataml load library service wrappers.
|
|
|
10
10
|
All teradataml wrappers to provide interface to load library service stored procedures
|
|
11
11
|
from Open Analytics Framework.
|
|
12
12
|
"""
|
|
13
|
+
import base64
|
|
13
14
|
import concurrent.futures
|
|
14
15
|
import functools
|
|
15
16
|
import json
|
|
16
17
|
import operator
|
|
17
18
|
import os
|
|
19
|
+
import warnings
|
|
20
|
+
from json.decoder import JSONDecodeError
|
|
21
|
+
from time import sleep, time
|
|
22
|
+
from urllib.parse import urlparse
|
|
18
23
|
|
|
19
24
|
import pandas as pd
|
|
20
|
-
import requests
|
|
21
25
|
|
|
22
|
-
from json.decoder import JSONDecodeError
|
|
23
26
|
from teradataml import configure
|
|
24
|
-
from teradataml.
|
|
25
|
-
from teradataml.
|
|
26
|
-
from teradataml.
|
|
27
|
+
from teradataml.clients.auth_client import _AuthWorkflow
|
|
28
|
+
from teradataml.clients.keycloak_client import _KeycloakManager
|
|
29
|
+
from teradataml.clients.pkce_client import _DAWorkflow
|
|
30
|
+
from teradataml.common.constants import (AsyncOpStatus, AsyncStatusColumns,
|
|
31
|
+
AuthMechs, HTTPRequest, TDServices)
|
|
27
32
|
from teradataml.common.exceptions import TeradataMlException
|
|
28
|
-
from teradataml.common.messages import Messages
|
|
29
33
|
from teradataml.common.messagecodes import MessageCodes
|
|
34
|
+
from teradataml.common.messages import Messages
|
|
30
35
|
from teradataml.common.utils import UtilFuncs
|
|
31
|
-
from teradataml.
|
|
32
|
-
from teradataml.
|
|
36
|
+
from teradataml.context.context import _get_user, get_connection
|
|
37
|
+
from teradataml.scriptmgmt.UserEnv import (UserEnv, _AuthToken,
|
|
38
|
+
_get_auth_token, _get_ccp_url,
|
|
39
|
+
_get_ues_url, _process_ues_response)
|
|
40
|
+
from teradataml.telemetry_utils.queryband import collect_queryband
|
|
33
41
|
from teradataml.utils.internal_buffer import _InternalBuffer
|
|
34
|
-
from teradataml.scriptmgmt.UserEnv import UserEnv, _get_auth_token, \
|
|
35
|
-
_process_ues_response, _get_ues_url, _AuthToken
|
|
36
|
-
from teradataml.utils.validators import _Validators
|
|
37
|
-
from time import time, sleep
|
|
38
|
-
import warnings
|
|
39
|
-
import webbrowser
|
|
40
|
-
from urllib.parse import parse_qs, urlparse
|
|
41
42
|
from teradataml.utils.utils import _async_run_id_info
|
|
42
|
-
from teradataml.
|
|
43
|
+
from teradataml.utils.validators import _Validators
|
|
44
|
+
|
|
43
45
|
|
|
44
46
|
@collect_queryband(queryband="LstBsEnv")
|
|
45
47
|
def list_base_envs():
|
|
@@ -197,7 +199,7 @@ def list_user_envs(env_name=None, **kwargs):
|
|
|
197
199
|
... 'python_3.9',
|
|
198
200
|
... 'Sales team environment.',
|
|
199
201
|
... conda_env=True)
|
|
200
|
-
Conda environment creation initiated
|
|
202
|
+
Conda environment creation initiated.
|
|
201
203
|
User environment 'Sales_cond_env' created.
|
|
202
204
|
|
|
203
205
|
# Example 1: List all available user environments.
|
|
@@ -303,7 +305,7 @@ def list_user_envs(env_name=None, **kwargs):
|
|
|
303
305
|
|
|
304
306
|
try:
|
|
305
307
|
response = UtilFuncs._http_request(_get_ues_url(), headers=_get_auth_token())
|
|
306
|
-
# Below condition is special case
|
|
308
|
+
# Below condition is special case handling when remove_all_envs() used by user, remove_all_envs()
|
|
307
309
|
# removes all the envs which result in a status_code 404 and due to which warnings provided in
|
|
308
310
|
# list_user_envs() not appears.
|
|
309
311
|
if response.status_code == 404 and "No user environments found." in response.text:
|
|
@@ -339,7 +341,7 @@ def list_user_envs(env_name=None, **kwargs):
|
|
|
339
341
|
# Return the DataFrame if not empty.
|
|
340
342
|
if len(pandas_df) > 0:
|
|
341
343
|
return pandas_df
|
|
342
|
-
|
|
344
|
+
|
|
343
345
|
print("No user environment(s) found.")
|
|
344
346
|
except (TeradataMlException, RuntimeError):
|
|
345
347
|
raise
|
|
@@ -451,8 +453,8 @@ def __create_envs(template):
|
|
|
451
453
|
except Exception as lib_installation_failure:
|
|
452
454
|
error_code = MessageCodes.FUNC_EXECUTION_FAILED
|
|
453
455
|
error_msg = Messages.get_message(error_code,
|
|
454
|
-
"'install_lib' request for enviornment: '{}'".format(env_name),
|
|
455
|
-
'\n'+str(lib_installation_failure))
|
|
456
|
+
"'install_lib' request for enviornment: '{}'".format(env_name),
|
|
457
|
+
'\n' + str(lib_installation_failure))
|
|
456
458
|
print(error_msg)
|
|
457
459
|
errored = errored or True
|
|
458
460
|
pass
|
|
@@ -747,9 +749,18 @@ def create_env(env_name=None, base_env=None, desc=None, template=None, conda_env
|
|
|
747
749
|
>>> fraud_detection_env = create_env('Fraud_detection_conda',
|
|
748
750
|
... 'python_3.8',
|
|
749
751
|
... 'Fraud detection through time matching',
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
752
|
+
... conda_env=True)
|
|
753
|
+
Conda environment creation initiated.
|
|
754
|
+
User environment 'Fraud_detection_conda' created.
|
|
755
|
+
|
|
756
|
+
# Example 5: Create a Conda R 4.2 environment with given name and
|
|
757
|
+
# description in the Vantage.
|
|
758
|
+
>>> conda_r_env = create_env('conda_r_env',
|
|
759
|
+
... 'r_4.2',
|
|
760
|
+
... 'Conda R environment',
|
|
761
|
+
... conda_env=True)
|
|
762
|
+
Conda environment creation initiated.
|
|
763
|
+
User environment 'conda_r_env' created.
|
|
753
764
|
"""
|
|
754
765
|
|
|
755
766
|
# Either env_name or template can be used.
|
|
@@ -774,7 +785,7 @@ def create_env(env_name=None, base_env=None, desc=None, template=None, conda_env
|
|
|
774
785
|
# Or if base_env is provided and not in the list of base envs.
|
|
775
786
|
# Note: By default python base env is obtained.
|
|
776
787
|
if configure.ues_url is not None and \
|
|
777
|
-
|
|
788
|
+
get_connection() is not None:
|
|
778
789
|
# Check if base_env is provided or not in the list of base envs.
|
|
779
790
|
|
|
780
791
|
# Check if user requested for conda environment but do not specify the base_env.
|
|
@@ -787,11 +798,11 @@ def create_env(env_name=None, base_env=None, desc=None, template=None, conda_env
|
|
|
787
798
|
# Check if base_env provided or not. If provided, check if it is available in
|
|
788
799
|
# the list of base envs. If not available, set base_env to the default python base env.
|
|
789
800
|
if not base_env or \
|
|
790
|
-
|
|
801
|
+
base_env.lower() not in list_base_envs()['base_name'].str.lower().to_list():
|
|
791
802
|
# Print warning message if base_env provided is not available.
|
|
792
803
|
if base_env:
|
|
793
|
-
print(f"Note: The specified base environment '{base_env}' is unavailable. "\
|
|
794
|
-
|
|
804
|
+
print(f"Note: The specified base environment '{base_env}' is unavailable. " \
|
|
805
|
+
"Using the default base environment as specified in the documentation.")
|
|
795
806
|
# Set base_env to the default
|
|
796
807
|
base_env = __get_default_base_env()
|
|
797
808
|
if not desc:
|
|
@@ -804,21 +815,25 @@ def create_env(env_name=None, base_env=None, desc=None, template=None, conda_env
|
|
|
804
815
|
response = UtilFuncs._http_request(
|
|
805
816
|
_get_ues_url(conda_env=conda_env), HTTPRequest.POST, headers=_get_auth_token(), json=data)
|
|
806
817
|
|
|
807
|
-
# UES
|
|
808
|
-
|
|
818
|
+
# Validate UES response.
|
|
819
|
+
_process_ues_response(api_name="create_env", response=response)
|
|
809
820
|
|
|
810
821
|
msg = "User environment '{}' created."
|
|
811
822
|
|
|
812
823
|
if conda_env:
|
|
813
|
-
print("Conda environment creation initiated")
|
|
824
|
+
print("Conda environment creation initiated.")
|
|
814
825
|
# Get claim_id.
|
|
815
826
|
claim_id = response.json().get("claim_id", "")
|
|
816
|
-
|
|
827
|
+
|
|
828
|
+
# Since create_env() for conda environment is internally
|
|
829
|
+
# asynchronous but exposed as synchronous API, keep polling
|
|
830
|
+
# the status of underlying asynchronous operation until
|
|
831
|
+
# it is either successful or errored.
|
|
817
832
|
__poll_claim_id_status(claim_id, "create_env")
|
|
818
833
|
print(msg.format(env_name))
|
|
819
834
|
|
|
820
835
|
# Return an instance of class UserEnv.
|
|
821
|
-
return UserEnv(env_name, base_env, desc)
|
|
836
|
+
return UserEnv(env_name, base_env, desc, conda_env)
|
|
822
837
|
|
|
823
838
|
except (TeradataMlException, RuntimeError):
|
|
824
839
|
raise
|
|
@@ -855,7 +870,7 @@ def _async_run_status_open_af(claim_id):
|
|
|
855
870
|
__get_claim_id_status('278381bf-e3b3-47ff-9ba5-c3b5d9007363')
|
|
856
871
|
"""
|
|
857
872
|
# Get the claim id status.
|
|
858
|
-
resp_data =
|
|
873
|
+
resp_data = _get_status(claim_id)
|
|
859
874
|
|
|
860
875
|
desc = _async_run_id_info.get(claim_id, {}).get("description", "Unknown")
|
|
861
876
|
get_details = lambda data: {AsyncStatusColumns.ADDITIONAL_DETAILS.value:
|
|
@@ -871,7 +886,7 @@ def _async_run_status_open_af(claim_id):
|
|
|
871
886
|
return [get_details(sub_step) for sub_step in resp_data]
|
|
872
887
|
|
|
873
888
|
|
|
874
|
-
def
|
|
889
|
+
def _get_status(claim_id):
|
|
875
890
|
"""
|
|
876
891
|
DESCRIPTION:
|
|
877
892
|
Internal function to get the status of a claim_id using
|
|
@@ -891,7 +906,7 @@ def __get_status(claim_id):
|
|
|
891
906
|
None
|
|
892
907
|
|
|
893
908
|
EXAMPLES:
|
|
894
|
-
|
|
909
|
+
_get_status('278381bf-e3b3-47ff-9ba5-c3b5d9007363')
|
|
895
910
|
"""
|
|
896
911
|
# Get the claim id status
|
|
897
912
|
response = UtilFuncs._http_request(_get_ues_url(env_type="fm",
|
|
@@ -1030,6 +1045,9 @@ def __manage_envs(env_name=None, api_name="remove_env", **kwargs):
|
|
|
1030
1045
|
|
|
1031
1046
|
try:
|
|
1032
1047
|
# Get the ues url for corresponding API.
|
|
1048
|
+
# While deleting environment, endpoint UES URL for deleting
|
|
1049
|
+
# normal and conda environment is same, unlike creating
|
|
1050
|
+
# normal and conda environment.
|
|
1033
1051
|
ues_url = _get_ues_url(env_name=env_name, api_name=api_name) if api_name == "remove_env" \
|
|
1034
1052
|
else _get_ues_url(remove_all_envs=True, api_name=api_name)
|
|
1035
1053
|
|
|
@@ -1048,7 +1066,7 @@ def __manage_envs(env_name=None, api_name="remove_env", **kwargs):
|
|
|
1048
1066
|
if api_name == "remove_env":
|
|
1049
1067
|
msg = "{2}list_user_envs(). If environment is not removed, " \
|
|
1050
1068
|
"check the status of asynchronous call using" \
|
|
1051
|
-
" async_run_status('{1}') or get_env('{0}').status('{1}')"
|
|
1069
|
+
" async_run_status('{1}') or get_env('{0}').status('{1}')". \
|
|
1052
1070
|
format(env_name, claim_id, msg)
|
|
1053
1071
|
else:
|
|
1054
1072
|
msg = "{0}async_run_status('{1}')".format(msg, claim_id)
|
|
@@ -1093,30 +1111,37 @@ def __poll_claim_id_status(claim_id, api_name="remove_env"):
|
|
|
1093
1111
|
Default Value: remove_env
|
|
1094
1112
|
Types: str
|
|
1095
1113
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
1114
|
RETURNS:
|
|
1099
1115
|
None.
|
|
1100
1116
|
|
|
1101
1117
|
RAISES:
|
|
1102
|
-
|
|
1118
|
+
TeradataMlException
|
|
1103
1119
|
|
|
1104
1120
|
EXAMPLES:
|
|
1105
1121
|
__poll_claim_id_status('cf7245f0-e962-4451-addf-efa7e123998d')
|
|
1106
1122
|
"""
|
|
1123
|
+
err_details = None
|
|
1107
1124
|
while True:
|
|
1108
1125
|
sleep(2)
|
|
1109
1126
|
|
|
1110
1127
|
# Poll the claim id to get the status.
|
|
1111
|
-
resp_data =
|
|
1128
|
+
resp_data = _get_status(claim_id)
|
|
1112
1129
|
|
|
1113
1130
|
# Breaking condition -
|
|
1114
1131
|
# For create_env and remove_env: Check for the 'Finished' stage in the list of resp.
|
|
1115
1132
|
# For remove_all_envs: above cond. and No user envs condition should break it .
|
|
1116
1133
|
for data in resp_data:
|
|
1117
|
-
if
|
|
1118
|
-
(api_name in ["create_env", "remove_all_envs"] and "Errored" in data["stage"]):
|
|
1134
|
+
if AsyncOpStatus.FINISHED.value in data["stage"]:
|
|
1119
1135
|
return
|
|
1136
|
+
elif AsyncOpStatus.ERRED.value in data["stage"]:
|
|
1137
|
+
err_details = data["details"]
|
|
1138
|
+
break
|
|
1139
|
+
if err_details:
|
|
1140
|
+
break
|
|
1141
|
+
|
|
1142
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.FUNC_EXECUTION_FAILED,
|
|
1143
|
+
api_name, err_details),
|
|
1144
|
+
MessageCodes.FUNC_EXECUTION_FAILED)
|
|
1120
1145
|
|
|
1121
1146
|
|
|
1122
1147
|
@collect_queryband(queryband="GtEnv")
|
|
@@ -1191,7 +1216,9 @@ def get_env(env_name):
|
|
|
1191
1216
|
# Return an instance of class UserEnv.
|
|
1192
1217
|
return UserEnv(userenv_row.env_name.values[0],
|
|
1193
1218
|
userenv_row.base_env_name.values[0],
|
|
1194
|
-
userenv_row.env_description.values[0]
|
|
1219
|
+
userenv_row.env_description.values[0],
|
|
1220
|
+
userenv_row.conda.values[0]
|
|
1221
|
+
)
|
|
1195
1222
|
except (TeradataMlException, RuntimeError) as tdemsg:
|
|
1196
1223
|
# TeradataMlException and RuntimeError are raised by list_user_envs.
|
|
1197
1224
|
# list_user_envs should be replaced with get_env in the error
|
|
@@ -1446,7 +1473,7 @@ def _remove_all_envs(env_type, **kwargs):
|
|
|
1446
1473
|
if env_type.capitalize() == "Py":
|
|
1447
1474
|
env_type = ["Python", "python"]
|
|
1448
1475
|
else:
|
|
1449
|
-
env_type = ["R"]
|
|
1476
|
+
env_type = ["R", "r"]
|
|
1450
1477
|
env_type_message = "R"
|
|
1451
1478
|
asynchronous = kwargs.get("asynchronous", False)
|
|
1452
1479
|
|
|
@@ -1485,7 +1512,7 @@ def _remove_all_envs(env_type, **kwargs):
|
|
|
1485
1512
|
if len(failed_envs) > 0:
|
|
1486
1513
|
emsg = ""
|
|
1487
1514
|
for env, tdemsg in failed_envs.items():
|
|
1488
|
-
emsg += "\nUser environment '{0}' failed to remove. Reason: {1}"\
|
|
1515
|
+
emsg += "\nUser environment '{0}' failed to remove. Reason: {1}" \
|
|
1489
1516
|
.format(env, tdemsg.args[0])
|
|
1490
1517
|
msg_code = MessageCodes.FUNC_EXECUTION_FAILED
|
|
1491
1518
|
error_msg = Messages.get_message(msg_code, "remove_all_envs()", emsg)
|
|
@@ -1598,23 +1625,94 @@ def get_user_env():
|
|
|
1598
1625
|
return configure._default_user_env
|
|
1599
1626
|
|
|
1600
1627
|
|
|
1628
|
+
def _validate_jwt_token(base_url, token_data):
|
|
1629
|
+
"""
|
|
1630
|
+
DESCRIPTION:
|
|
1631
|
+
Function to validate the authentication token generated using PAT and PEM file.
|
|
1632
|
+
|
|
1633
|
+
PARAMETERS:
|
|
1634
|
+
base_url:
|
|
1635
|
+
Required Argument.
|
|
1636
|
+
Specifies the endpoint URL for a given environment on VantageCloud Lake.
|
|
1637
|
+
Types: str
|
|
1638
|
+
|
|
1639
|
+
token_data:
|
|
1640
|
+
Required Argument.
|
|
1641
|
+
Specifies the JWT token to be authenticated.
|
|
1642
|
+
|
|
1643
|
+
RETURNS:
|
|
1644
|
+
Boolan flag representing validation status.
|
|
1645
|
+
* True: Indicates that token is valid.
|
|
1646
|
+
* None: Indicates that token is not validated.
|
|
1647
|
+
|
|
1648
|
+
RAISES:
|
|
1649
|
+
TeradataMlException
|
|
1650
|
+
|
|
1651
|
+
EXAMPLES:
|
|
1652
|
+
Example 1: Validate JWT token.
|
|
1653
|
+
>>> _validate_jwt_token(base_url, token_data)
|
|
1654
|
+
|
|
1655
|
+
"""
|
|
1656
|
+
# Extract environment id from base_url.
|
|
1657
|
+
try:
|
|
1658
|
+
url_parser = urlparse(base_url)
|
|
1659
|
+
env_id = url_parser.path.split("accounts/")[1].split("/")[0]
|
|
1660
|
+
if not env_id:
|
|
1661
|
+
raise
|
|
1662
|
+
except Exception:
|
|
1663
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.FUNC_EXECUTION_FAILED,
|
|
1664
|
+
"set_auth_token",
|
|
1665
|
+
"Use valid value for 'base_url'"),
|
|
1666
|
+
MessageCodes.FUNC_EXECUTION_FAILED)
|
|
1667
|
+
|
|
1668
|
+
valid_token = None
|
|
1669
|
+
try:
|
|
1670
|
+
response = UtilFuncs._http_request(url="{}/{}/{}/{}".format(_get_ccp_url(base_url),
|
|
1671
|
+
"api", "accounts", env_id),
|
|
1672
|
+
method_type=HTTPRequest.GET,
|
|
1673
|
+
headers={"Authorization": "Bearer {}".format(token_data)})
|
|
1674
|
+
if 200 <= response.status_code < 300: # Authorized access.
|
|
1675
|
+
valid_token = True
|
|
1676
|
+
elif 400 <= response.status_code < 500: # Unauthorized access.
|
|
1677
|
+
valid_token = False
|
|
1678
|
+
except:
|
|
1679
|
+
pass
|
|
1680
|
+
|
|
1681
|
+
if valid_token is False:
|
|
1682
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.FUNC_EXECUTION_FAILED,
|
|
1683
|
+
"set_auth_token",
|
|
1684
|
+
"Use valid values for input arguments ['base_url',"
|
|
1685
|
+
" 'pat_token', 'pem_file']."),
|
|
1686
|
+
MessageCodes.FUNC_EXECUTION_FAILED)
|
|
1687
|
+
return valid_token
|
|
1688
|
+
|
|
1689
|
+
|
|
1601
1690
|
@collect_queryband(queryband="StAthTkn")
|
|
1602
1691
|
def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None, **kwargs):
|
|
1603
1692
|
"""
|
|
1604
1693
|
DESCRIPTION:
|
|
1605
|
-
Function to set the
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
User must have a privilege to login with a NULL password to use set_auth_token().
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1694
|
+
Function to set the authentication token required to access services running on
|
|
1695
|
+
Teradata Vantage.
|
|
1696
|
+
Notes:
|
|
1697
|
+
* User must have a privilege to login with a NULL password to use set_auth_token().
|
|
1698
|
+
Refer to GRANT LOGON section in Teradata Documentation for more details.
|
|
1699
|
+
* When "auth_mech" is not specified, arguments are used in the following combination
|
|
1700
|
+
to derive authentication mechanism.
|
|
1701
|
+
* If "base_url" and "client_id" are specified then token generation is done through OAuth.
|
|
1702
|
+
* If "base_url", "pat_token", "pem_file" are specified then token generation is done using PAT.
|
|
1703
|
+
* If "base_url", "username" and "password" are specified then authentication is done via
|
|
1704
|
+
Basic authentication mechanism using user credentials.
|
|
1705
|
+
* If "base_url" and "auth_token" are specified then readily available token is used.
|
|
1706
|
+
* If only "base_url" is specified then token generation is done through OAuth.
|
|
1707
|
+
* Refresh token works only for OAuth authentication.
|
|
1708
|
+
* Use the argument "kid" only when key used during the pem file generation is different
|
|
1709
|
+
from pem file name. For example, if you use the key as 'key1' while generating pem file
|
|
1710
|
+
and the name of the pem file is `key1(1).pem`, then pass value 'key1' to the argument "kid".
|
|
1613
1711
|
|
|
1614
1712
|
PARAMETERS:
|
|
1615
1713
|
base_url:
|
|
1616
1714
|
Required Argument.
|
|
1617
|
-
Specifies the
|
|
1715
|
+
Specifies the endpoint URL for a given environment on Teradata Vantage system.
|
|
1618
1716
|
Types: str
|
|
1619
1717
|
|
|
1620
1718
|
client_id:
|
|
@@ -1631,35 +1729,99 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
|
|
|
1631
1729
|
pem_file:
|
|
1632
1730
|
Required, if PAT authentication is to be used, optional otherwise.
|
|
1633
1731
|
Specifies the path to private key file which is generated from VantageCloud Lake Console.
|
|
1732
|
+
Note:
|
|
1733
|
+
Teradata recommends not to change the name of the file generated from VantageCloud Lake
|
|
1734
|
+
Console. If the name of the file is changed, then authentication token generated from
|
|
1735
|
+
this function will not work.
|
|
1634
1736
|
Types: str
|
|
1635
1737
|
|
|
1636
1738
|
**kwargs:
|
|
1637
1739
|
username:
|
|
1740
|
+
Optional Argument.
|
|
1638
1741
|
Specifies the user for which authentication is to be requested.
|
|
1639
1742
|
If not specified, then user associated with current connection is used.
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1743
|
+
Notes:
|
|
1744
|
+
* Use this option only if name of the database username has lowercase letters.
|
|
1745
|
+
* This option is used only for PAT and not for OAuth.
|
|
1643
1746
|
Types: str
|
|
1644
1747
|
|
|
1645
1748
|
expiration_time:
|
|
1646
|
-
|
|
1647
|
-
|
|
1749
|
+
Optional Argument.
|
|
1750
|
+
Specifies the expiration time of the token in seconds. After expiry time, JWT
|
|
1751
|
+
token expires and UserEnv methods does not work, user should regenerate the token.
|
|
1648
1752
|
Note:
|
|
1649
|
-
This option is used only for PAT and not for OAuth.
|
|
1753
|
+
* This option is used only for PAT and not for OAuth.
|
|
1650
1754
|
Default Value: 31536000
|
|
1651
1755
|
Types: int
|
|
1652
1756
|
|
|
1653
1757
|
auth_token:
|
|
1654
|
-
Optional
|
|
1655
|
-
Specifies the authentication token to
|
|
1758
|
+
Optional Argument.
|
|
1759
|
+
Specifies the authentication token required to access services running
|
|
1760
|
+
on Teradata Vantage.
|
|
1656
1761
|
Notes:
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1762
|
+
* If "auth_token" is set through this function, then this function
|
|
1763
|
+
should always be used only after create_context().
|
|
1764
|
+
* Use this option only if user has got JWT token and wants to set
|
|
1765
|
+
the same instead of generating it again from this function.
|
|
1766
|
+
|
|
1767
|
+
Types: str
|
|
1768
|
+
|
|
1769
|
+
kid:
|
|
1770
|
+
Optional Argument.
|
|
1771
|
+
Specifies the name of the key which is used while generating 'pem_file'.
|
|
1772
|
+
Types: str
|
|
1773
|
+
|
|
1774
|
+
password:
|
|
1775
|
+
Optional Argument.
|
|
1776
|
+
Specifies the password for database user to be used for Basic authentication.
|
|
1777
|
+
Types: str
|
|
1778
|
+
|
|
1779
|
+
auth_url:
|
|
1780
|
+
Optional Argument.
|
|
1781
|
+
Specifies the endpoint URL for a keycloak server.
|
|
1661
1782
|
Types: str
|
|
1662
1783
|
|
|
1784
|
+
rest_client:
|
|
1785
|
+
Optional Argument.
|
|
1786
|
+
Specifies the service for which keycloak token is to be generated.
|
|
1787
|
+
Permitted values: "VECTORSTORE"
|
|
1788
|
+
Default value: "VECTORSTORE"
|
|
1789
|
+
Types: str
|
|
1790
|
+
|
|
1791
|
+
auth_mech:
|
|
1792
|
+
Optional Argument.
|
|
1793
|
+
Specifies the mechanism to be used for generating authentication token.
|
|
1794
|
+
Note:
|
|
1795
|
+
* When "auth_mech" is provided, other arguments are used in the following
|
|
1796
|
+
combination as per value of "auth_mech":
|
|
1797
|
+
* OAuth: Token generation is done through OAuth by using client id
|
|
1798
|
+
which can be sepcified by user in "client_id" argument or
|
|
1799
|
+
can be derived internally from "base_url".
|
|
1800
|
+
* PAT: Token generation is done using "pat_token" and "pem_file".
|
|
1801
|
+
* BASIC: Authentication is done via Basic authentication mechanism
|
|
1802
|
+
using user credentials passed in "username" and "password"
|
|
1803
|
+
arguments.
|
|
1804
|
+
* JWT: Readily available token in "auth_token" argument is used.
|
|
1805
|
+
* KEYCLOAK: Token generation is done using keycloak.
|
|
1806
|
+
Permitted Values: "OAuth", "PAT", "BASIC", "JWT", "KEYCLOAK".
|
|
1807
|
+
Types: str
|
|
1808
|
+
|
|
1809
|
+
validate_jwt:
|
|
1810
|
+
Optional Argument.
|
|
1811
|
+
Specifies whether to validate generated JWT token or not.
|
|
1812
|
+
Note:
|
|
1813
|
+
* Applicable only when "auth_mech" is "PAT".
|
|
1814
|
+
Default value: True
|
|
1815
|
+
Types: boolean
|
|
1816
|
+
|
|
1817
|
+
valid_from:
|
|
1818
|
+
Optional Argument.
|
|
1819
|
+
Specifies epoch seconds representing time from which JWT token will be valid.
|
|
1820
|
+
Note:
|
|
1821
|
+
* Applicable only when "auth_mech" is "PAT".
|
|
1822
|
+
Default value: None
|
|
1823
|
+
Types: int
|
|
1824
|
+
|
|
1663
1825
|
RETURNS:
|
|
1664
1826
|
True, if the operation is successful.
|
|
1665
1827
|
|
|
@@ -1671,10 +1833,14 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
|
|
|
1671
1833
|
# Example 1: Set the Authentication token using default client_id.
|
|
1672
1834
|
>>> import getpass
|
|
1673
1835
|
>>> set_auth_token(base_url=getpass.getpass("ues_url : "))
|
|
1836
|
+
Authentication token is generated and set for the session.
|
|
1837
|
+
True
|
|
1674
1838
|
|
|
1675
1839
|
# Example 2: Set the Authentication token by specifying the client_id.
|
|
1676
1840
|
>>> set_auth_token(base_url=getpass.getpass("base_url : "),
|
|
1677
1841
|
... client_id=getpass.getpass("client_id : "))
|
|
1842
|
+
Authentication token is generated and set for the session.
|
|
1843
|
+
True
|
|
1678
1844
|
|
|
1679
1845
|
# Example 3: Set the Authentication token by specifying the "pem_file" and "pat_token"
|
|
1680
1846
|
# without specifying "username".
|
|
@@ -1682,6 +1848,7 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
|
|
|
1682
1848
|
>>> set_auth_token(base_url=getpass.getpass("base_url : "),
|
|
1683
1849
|
... pat_token=getpass.getpass("pat_token : "),
|
|
1684
1850
|
... pem_file=getpass.getpass("pem_file : "))
|
|
1851
|
+
Authentication token is generated, authenticated and set for the session.
|
|
1685
1852
|
True
|
|
1686
1853
|
|
|
1687
1854
|
# Example 4: Set the Authentication token by specifying the "pem_file" and "pat_token"
|
|
@@ -1689,85 +1856,201 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
|
|
|
1689
1856
|
>>> import getpass
|
|
1690
1857
|
>>> set_auth_token(base_url=getpass.getpass("base_url : "),
|
|
1691
1858
|
... pat_token=getpass.getpass("pat_token : "),
|
|
1692
|
-
... pem_file=getpass.getpass("pem_file : ")
|
|
1693
|
-
... username
|
|
1859
|
+
... pem_file=getpass.getpass("pem_file : "),
|
|
1860
|
+
... username=getpass.getpass("username : "))
|
|
1861
|
+
Authentication token is generated, authenticated and set for the session.
|
|
1862
|
+
True
|
|
1863
|
+
|
|
1864
|
+
# Example 5: Set the Authentication token by specifying the "pem_file" and "pat_token"
|
|
1865
|
+
# and "kid".
|
|
1866
|
+
>>> import getpass
|
|
1867
|
+
>>> set_auth_token(base_url=getpass.getpass("base_url : "),
|
|
1868
|
+
... pat_token=getpass.getpass("pat_token : "),
|
|
1869
|
+
... pem_file=getpass.getpass("pem_file : ")
|
|
1870
|
+
... kid="key1")
|
|
1871
|
+
Authentication token is generated, authenticated and set for the session.
|
|
1872
|
+
True
|
|
1873
|
+
|
|
1874
|
+
# Example 6: Set the authentication token via Basic Authentication mechanism by
|
|
1875
|
+
# specifying the "base_url", "username" and "password".
|
|
1876
|
+
>>> import getpass
|
|
1877
|
+
>>> set_auth_token(base_url=getpass.getpass("base_url : "),
|
|
1878
|
+
... username=getpass.getpass("username : "),
|
|
1879
|
+
... password=getpass.getpass("password : "))
|
|
1880
|
+
Authentication token is generated and set for the session.
|
|
1881
|
+
True
|
|
1882
|
+
|
|
1883
|
+
# Example 7: Set the authentication token for by specifying "base_url" and
|
|
1884
|
+
# "auth_mech" as "OAuth".
|
|
1885
|
+
>>> import getpass
|
|
1886
|
+
>>> set_auth_token(base_url=getpass.getpass("base_url : "),
|
|
1887
|
+
... auth_mech="OAuth")
|
|
1888
|
+
Authentication token is generated and set for the session.
|
|
1889
|
+
True
|
|
1890
|
+
|
|
1891
|
+
# Example 8: Set the authentication token for by specifying "base_url", "auth_url"
|
|
1892
|
+
# "password" and "rest_client" and generating keycloak token internally.
|
|
1893
|
+
>>> import getpass
|
|
1894
|
+
>>> set_auth_token(base_url=getpass.getpass("base_url : "),
|
|
1895
|
+
... auth_url=getpass.getpass("auth_url : "),
|
|
1896
|
+
... password=getpass.getpass("password : "),
|
|
1897
|
+
... rest_client=getpass.getpass("rest_client : "))
|
|
1898
|
+
Authentication token is generated and set for the session.
|
|
1694
1899
|
True
|
|
1900
|
+
|
|
1695
1901
|
"""
|
|
1902
|
+
|
|
1696
1903
|
# Deriving global connection using get_connection().
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
raise TeradataMlException(Messages.get_message(MessageCodes.INVALID_CONTEXT_CONNECTION),
|
|
1904
|
+
if get_connection() is None:
|
|
1905
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.INVALID_CONTEXT_CONNECTION),
|
|
1700
1906
|
MessageCodes.INVALID_CONTEXT_CONNECTION)
|
|
1701
1907
|
|
|
1702
|
-
#
|
|
1703
|
-
|
|
1908
|
+
# Remove keys from _InternalBuffer which are interrelated to base_url and authentication token.
|
|
1909
|
+
_InternalBuffer.remove_keys(['list_base_envs', 'default_base_env',
|
|
1910
|
+
'vs_session_id', 'vs_header'])
|
|
1704
1911
|
|
|
1912
|
+
# ---------------------------------ARGUMENT VALIDATION------------------------------------------------------
|
|
1913
|
+
# STEP 1: Validate arguments for allowed types.
|
|
1914
|
+
# ----------------------------------------------------------------------------------------------------------
|
|
1705
1915
|
__arg_info_matrix = []
|
|
1706
1916
|
__arg_info_matrix.append(["base_url", base_url, True, (str), True])
|
|
1707
|
-
__arg_info_matrix.append(["ues_url", ues_url, True, (str), True])
|
|
1708
1917
|
__arg_info_matrix.append(["client_id", client_id, True, (str), True])
|
|
1709
1918
|
__arg_info_matrix.append(["pat_token", pat_token, True, (str), True])
|
|
1710
1919
|
__arg_info_matrix.append(["pem_file", pem_file, True, (str), True])
|
|
1711
1920
|
|
|
1712
|
-
|
|
1713
|
-
|
|
1921
|
+
# Get keyword arguments.
|
|
1922
|
+
ues_url = kwargs.get("ues_url", None)
|
|
1923
|
+
__arg_info_matrix.append(["ues_url", ues_url, True, (str), True])
|
|
1924
|
+
|
|
1925
|
+
username = kwargs.get("username", _get_user())
|
|
1926
|
+
__arg_info_matrix.append(["username", username, True, (str), True])
|
|
1927
|
+
|
|
1928
|
+
password = kwargs.get("password", None)
|
|
1929
|
+
__arg_info_matrix.append(["password", password, True, (str), True])
|
|
1714
1930
|
|
|
1715
1931
|
auth_token = kwargs.get("auth_token")
|
|
1716
|
-
__arg_info_matrix.append(
|
|
1932
|
+
__arg_info_matrix.append(["auth_token", auth_token, True, (str), True])
|
|
1717
1933
|
|
|
1718
|
-
expiration_time = kwargs.get("expiration_time", 31536000)
|
|
1719
|
-
__arg_info_matrix.append(
|
|
1934
|
+
expiration_time = kwargs.get("expiration_time", 31536000) # 31536000 seconds meaning 365 days.
|
|
1935
|
+
__arg_info_matrix.append(["expiration_time", expiration_time, True, (int), True])
|
|
1936
|
+
|
|
1937
|
+
kid = kwargs.get("kid")
|
|
1938
|
+
__arg_info_matrix.append(["kid", kid, True, (str), True])
|
|
1939
|
+
|
|
1940
|
+
auth_url = kwargs.get("auth_url", None)
|
|
1941
|
+
__arg_info_matrix.append(["auth_url", auth_url, True, (str), True])
|
|
1942
|
+
|
|
1943
|
+
rest_client = kwargs.get("rest_client", "VECTORSTORE")
|
|
1944
|
+
__arg_info_matrix.append(["rest_client", rest_client, True, (str), True, [svc.name for svc in TDServices]])
|
|
1945
|
+
|
|
1946
|
+
auth_mech = kwargs.get("auth_mech", None)
|
|
1947
|
+
__arg_info_matrix.append(["auth_mech", auth_mech, True, (str), True, [mech.name for mech in AuthMechs]])
|
|
1948
|
+
|
|
1949
|
+
validate_jwt = kwargs.get("validate_jwt", True)
|
|
1950
|
+
__arg_info_matrix.append(["validate_jwt", validate_jwt, True, (bool)])
|
|
1951
|
+
|
|
1952
|
+
valid_from = kwargs.get("valid_from", None)
|
|
1953
|
+
__arg_info_matrix.append(["valid_from", valid_from, True, int])
|
|
1720
1954
|
|
|
1721
1955
|
# Validate arguments.
|
|
1722
1956
|
_Validators._validate_function_arguments(__arg_info_matrix)
|
|
1723
1957
|
|
|
1958
|
+
# ---------------------------------BASE_URL PROCESSING------------------------------------------------------
|
|
1959
|
+
# STEP 2: Process base_url/ues_url and set applicable config options.
|
|
1960
|
+
# ----------------------------------------------------------------------------------------------------------
|
|
1961
|
+
|
|
1724
1962
|
# base_url should not end with 'open-analytics' or 'data-insights'
|
|
1725
1963
|
if base_url:
|
|
1726
1964
|
if base_url.endswith('open-analytics') or base_url.endswith('data-insights'):
|
|
1727
1965
|
message = Messages.get_message(MessageCodes.ARG_NONE,
|
|
1728
|
-
"base_url", "ending with 'data-insights' or 'open-analytics",
|
|
1966
|
+
"base_url", "ending with 'data-insights' or 'open-analytics", "")
|
|
1729
1967
|
raise TeradataMlException(message, MessageCodes.ARG_NONE)
|
|
1730
1968
|
|
|
1731
1969
|
# Set the vector_store_base_url. This should only be done if base_url is set.
|
|
1732
1970
|
# In case ues_url is set, vector_store_base_url should not be set.
|
|
1733
1971
|
configure._vector_store_base_url = f'{base_url}/data-insights'
|
|
1734
1972
|
|
|
1973
|
+
if ues_url:
|
|
1974
|
+
# If incorrectly formatted UES service URL is passed, set it to None
|
|
1975
|
+
# and let further validation raise error.
|
|
1976
|
+
if not (ues_url.endswith('open-analytics') or ues_url.endswith('user-environment-service/api/v1/')):
|
|
1977
|
+
ues_url = None
|
|
1978
|
+
|
|
1735
1979
|
# If ues_url is provided, then use it as base_url.
|
|
1736
|
-
base_url =
|
|
1980
|
+
base_url = ues_url if ues_url else base_url
|
|
1981
|
+
|
|
1982
|
+
if not (base_url or ues_url):
|
|
1983
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.MISSING_ARGS, ["base_url"]),
|
|
1984
|
+
MessageCodes.MISSING_ARGS)
|
|
1737
1985
|
|
|
1738
1986
|
# Set the OpenAF url.
|
|
1739
|
-
# If ues_url is present use that otherwise generate it from base_url.
|
|
1987
|
+
# If ues_url is present, then use that otherwise generate it from base_url.
|
|
1740
1988
|
configure.ues_url = ues_url if ues_url else f'{base_url}/open-analytics'
|
|
1741
1989
|
|
|
1742
|
-
#
|
|
1743
|
-
if auth_token:
|
|
1744
|
-
_InternalBuffer.add(auth_token=_AuthToken(token=auth_token))
|
|
1745
|
-
return True
|
|
1746
|
-
|
|
1747
|
-
if client_id and any([pat_token, pem_file]):
|
|
1748
|
-
message = Messages.get_message(MessageCodes.EITHER_THIS_OR_THAT_ARGUMENT,
|
|
1749
|
-
"client_id", "pat_token' and 'pem_file")
|
|
1750
|
-
raise TeradataMlException(message, MessageCodes.EITHER_THIS_OR_THAT_ARGUMENT)
|
|
1751
|
-
|
|
1752
|
-
if client_id is None:
|
|
1753
|
-
if (pat_token and pem_file is None) or (pem_file and pat_token is None):
|
|
1754
|
-
message = Messages.get_message(MessageCodes.MUST_PASS_ARGUMENT,
|
|
1755
|
-
"pat_token", "pem_file")
|
|
1756
|
-
raise TeradataMlException(message, MessageCodes.MUST_PASS_ARGUMENT)
|
|
1757
|
-
|
|
1758
|
-
# Check if pem file exists.
|
|
1759
|
-
if pem_file is not None:
|
|
1760
|
-
_Validators._validate_file_exists(pem_file)
|
|
1761
|
-
|
|
1762
|
-
# Extract the base URL.
|
|
1990
|
+
# Extract the base URL and org id.
|
|
1763
1991
|
url_parser = urlparse(base_url)
|
|
1764
1992
|
parsed_base_url = "{}://{}".format(url_parser.scheme, url_parser.netloc)
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
#
|
|
1768
|
-
|
|
1993
|
+
org_id = url_parser.netloc.split('.')[0]
|
|
1994
|
+
|
|
1995
|
+
# ---------------------------------TOKEN GENERATION------------------------------------------------------
|
|
1996
|
+
# STEP 3: Based on auth_mech, generate authentication token data and store in _InternalBuffer.
|
|
1997
|
+
# Note: auth_mech can be user-provided or can be derived from valid combination of supporting parameters.
|
|
1998
|
+
# --------------------------------------------------------------------------------------------------------
|
|
1999
|
+
if auth_mech:
|
|
2000
|
+
auth_mech = auth_mech.lower()
|
|
2001
|
+
if auth_mech == 'oauth':
|
|
2002
|
+
pat_token = pem_file = password = auth_token = auth_url = None
|
|
2003
|
+
elif auth_mech == 'jwt':
|
|
2004
|
+
pat_token = pem_file = password = client_id = auth_url = None
|
|
2005
|
+
elif auth_mech == 'basic':
|
|
2006
|
+
pat_token = pem_file = auth_token = client_id = auth_url = None
|
|
2007
|
+
elif auth_mech == 'pat':
|
|
2008
|
+
password = client_id = auth_token = auth_url = None
|
|
2009
|
+
elif auth_mech == 'keycloak':
|
|
2010
|
+
pat_token = pem_file = auth_token = client_id = None
|
|
2011
|
+
|
|
2012
|
+
# Validate arguments for mutual exclusiveness.
|
|
2013
|
+
all_groups_none = \
|
|
2014
|
+
_Validators._validate_mutually_exclusive_argument_groups({"client_id": client_id},
|
|
2015
|
+
{"auth_token": auth_token},
|
|
2016
|
+
{"pat_token": pat_token,
|
|
2017
|
+
"pem_file": pem_file},
|
|
2018
|
+
{"password": password} if not auth_url else
|
|
2019
|
+
{"password": password, "auth_url": auth_url},
|
|
2020
|
+
return_all_falsy_status=True)
|
|
2021
|
+
|
|
2022
|
+
# Determine authentication mechanism from availability of supportive arguments.
|
|
2023
|
+
if auth_mech is None:
|
|
2024
|
+
if auth_token:
|
|
2025
|
+
auth_mech = 'jwt'
|
|
2026
|
+
elif any([pat_token, pem_file]):
|
|
2027
|
+
auth_mech = 'pat'
|
|
2028
|
+
elif auth_url:
|
|
2029
|
+
auth_mech = 'keycloak'
|
|
2030
|
+
elif password:
|
|
2031
|
+
# Authentication is done via Basic authentication mechanism
|
|
2032
|
+
# by passing 'basic' field in header.
|
|
2033
|
+
auth_mech = 'basic'
|
|
2034
|
+
# When all supporting arguments are None, default mechanism is OAuth.
|
|
2035
|
+
elif client_id or all_groups_none:
|
|
2036
|
+
auth_mech = 'oauth'
|
|
2037
|
+
|
|
2038
|
+
token_validated = False
|
|
2039
|
+
# Generate and use authentication data as per authentication mechanism.
|
|
2040
|
+
if auth_mech == 'jwt':
|
|
2041
|
+
if not auth_token:
|
|
2042
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.MISSING_ARGS, ["auth_token"]),
|
|
2043
|
+
MessageCodes.MISSING_ARGS)
|
|
2044
|
+
# Validate JWT token if base_url points to CCP environment.
|
|
2045
|
+
# TODO: Uncomment when mechanism to validate JWT for AI-On-prem system is available.
|
|
2046
|
+
# if not ues_url:
|
|
2047
|
+
# token_validated = _validate_jwt_token(base_url, auth_token)
|
|
2048
|
+
|
|
2049
|
+
_InternalBuffer.add(auth_token=_AuthToken(token=auth_token,
|
|
2050
|
+
auth_type='bearer'))
|
|
2051
|
+
elif auth_mech == 'oauth':
|
|
1769
2052
|
configure._oauth = True
|
|
1770
|
-
client_id = "{}-oaf-device".format(
|
|
2053
|
+
client_id = "{}-oaf-device".format(org_id) if client_id is None else client_id
|
|
1771
2054
|
da_wf = _DAWorkflow(parsed_base_url, client_id)
|
|
1772
2055
|
token_data = da_wf._get_token_data()
|
|
1773
2056
|
|
|
@@ -1777,34 +2060,72 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
|
|
|
1777
2060
|
configure._auth_token_expiry_time = time() + token_data["expires_in"] - 15
|
|
1778
2061
|
|
|
1779
2062
|
# Store the jwt token in internal class attribute.
|
|
1780
|
-
_InternalBuffer.add(auth_token=_AuthToken(token=token_data["access_token"]
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
2063
|
+
_InternalBuffer.add(auth_token=_AuthToken(token=token_data["access_token"],
|
|
2064
|
+
auth_type='bearer'))
|
|
2065
|
+
elif auth_mech == 'pat':
|
|
2066
|
+
if any([pat_token, pem_file]):
|
|
2067
|
+
_Validators._validate_mutually_inclusive_n_arguments(pat_token=pat_token,
|
|
2068
|
+
pem_file=pem_file)
|
|
2069
|
+
else:
|
|
2070
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.MISSING_ARGS, ["pat_token", "pem_file"]),
|
|
2071
|
+
MessageCodes.MISSING_ARGS)
|
|
2072
|
+
|
|
2073
|
+
# Check if pem file exists.
|
|
2074
|
+
if pem_file is not None:
|
|
2075
|
+
_Validators._validate_file_exists(pem_file)
|
|
2076
|
+
|
|
2077
|
+
# Generate JWT token.
|
|
2078
|
+
auth_wf = _AuthWorkflow({"base_url": parsed_base_url,
|
|
2079
|
+
"org_id": org_id,
|
|
2080
|
+
"pat_token": pat_token,
|
|
2081
|
+
"pem_file": pem_file,
|
|
2082
|
+
"username": username,
|
|
2083
|
+
"expiration_time": expiration_time,
|
|
2084
|
+
"kid": kid,
|
|
2085
|
+
"valid_from": valid_from})
|
|
2086
|
+
token_data = auth_wf._proxy_jwt()
|
|
1791
2087
|
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
state_dict["org_id"] = org_id
|
|
1796
|
-
state_dict["pat_token"] = pat_token
|
|
1797
|
-
state_dict["pem_file"] = pem_file
|
|
1798
|
-
state_dict["username"] = username
|
|
1799
|
-
state_dict["expiration_time"] = expiration_time
|
|
2088
|
+
if validate_jwt:
|
|
2089
|
+
# Validate generated JWT token.
|
|
2090
|
+
token_validated = _validate_jwt_token(base_url, token_data)
|
|
1800
2091
|
|
|
1801
|
-
auth_wf = _AuthWorkflow(state_dict)
|
|
1802
|
-
token_data = auth_wf._proxy_jwt()
|
|
1803
2092
|
# Store the jwt token in internal class attribute.
|
|
1804
|
-
_InternalBuffer.add(auth_token=_AuthToken(token=token_data
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
2093
|
+
_InternalBuffer.add(auth_token=_AuthToken(token=token_data,
|
|
2094
|
+
auth_type='bearer'))
|
|
2095
|
+
elif auth_mech == 'basic':
|
|
2096
|
+
if not password:
|
|
2097
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.MISSING_ARGS, ["password"]),
|
|
2098
|
+
MessageCodes.MISSING_ARGS)
|
|
2099
|
+
credentials = f"{username}:{password}"
|
|
2100
|
+
# Encode the credentials string using Base64.
|
|
2101
|
+
encoded_credentials = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')
|
|
2102
|
+
# Store the header data in internal class attribute.
|
|
2103
|
+
_InternalBuffer.add(auth_token=_AuthToken(token=encoded_credentials,
|
|
2104
|
+
auth_type='basic'))
|
|
2105
|
+
elif auth_mech == 'keycloak':
|
|
2106
|
+
_Validators._validate_missing_required_arguments([["password", password, False, (str), True],
|
|
2107
|
+
["auth_url", auth_url, False, (str), True]
|
|
2108
|
+
])
|
|
2109
|
+
token_generator = _KeycloakManager(auth_url=auth_url,
|
|
2110
|
+
client_id=TDServices[rest_client].value)
|
|
2111
|
+
|
|
2112
|
+
# Store manager object in _InternalBuffer in order to generate token after expiry time.
|
|
2113
|
+
_InternalBuffer.add(keycloak_manager=token_generator)
|
|
2114
|
+
try:
|
|
2115
|
+
token_data = token_generator.generate_token(username=username,
|
|
2116
|
+
password=password)
|
|
2117
|
+
except:
|
|
2118
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.FUNC_EXECUTION_FAILED,
|
|
2119
|
+
"set_auth_token",
|
|
2120
|
+
"Failed to generate keycloak token."),
|
|
2121
|
+
MessageCodes.FUNC_EXECUTION_FAILED)
|
|
2122
|
+
|
|
2123
|
+
_InternalBuffer.add(auth_token=_AuthToken(token=token_data,
|
|
2124
|
+
auth_type='keycloak'))
|
|
2125
|
+
|
|
2126
|
+
if token_validated:
|
|
2127
|
+
print("Authentication token is generated, authenticated and set for the session.")
|
|
2128
|
+
else:
|
|
2129
|
+
print("Authentication token is generated and set for the session.")
|
|
1809
2130
|
|
|
1810
2131
|
return True
|