Skip to content

Commit 552b764

Browse files
jshum2479robertpatrick
authored andcommitted
Wdt 903 - support discovering template datasources - RCUDbInfo
1 parent e252fb9 commit 552b764

File tree

9 files changed

+340
-21
lines changed

9 files changed

+340
-21
lines changed

core/src/main/python/discover.py

+210-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
The entry point for the discoverDomain tool.
66
"""
7-
import os
7+
import os, re
88
import sys
99

1010
from java.io import File
@@ -13,6 +13,7 @@
1313
from java.lang import IllegalStateException
1414
from java.lang import String
1515
from java.lang import System
16+
from java.util import HashSet
1617
from oracle.weblogic.deploy.aliases import AliasException
1718
from oracle.weblogic.deploy.discover import DiscoverException
1819
from oracle.weblogic.deploy.json import JsonException
@@ -27,10 +28,10 @@
2728

2829
sys.path.insert(0, os.path.dirname(os.path.realpath(sys.argv[0])))
2930

31+
from wlsdeploy.aliases import alias_constants
3032
from wlsdeploy.aliases import model_constants
3133
from wlsdeploy.aliases.aliases import Aliases
3234
from wlsdeploy.aliases.location_context import LocationContext
33-
from wlsdeploy.aliases.model_constants import DOMAIN_INFO
3435
from wlsdeploy.aliases.validation_codes import ValidationCodes
3536
from wlsdeploy.aliases.wlst_modes import WlstModes
3637
from wlsdeploy.exception import exception_helper
@@ -45,6 +46,7 @@
4546
from wlsdeploy.tool.discover.resources_discoverer import ResourcesDiscoverer
4647
from wlsdeploy.tool.discover.security_provider_data_discoverer import SecurityProviderDataDiscoverer
4748
from wlsdeploy.tool.discover.topology_discoverer import TopologyDiscoverer
49+
from wlsdeploy.tool.encrypt import encryption_utils
4850
from wlsdeploy.tool.util import filter_helper
4951
from wlsdeploy.tool.util import model_context_helper
5052
from wlsdeploy.tool.util.credential_injector import CredentialInjector
@@ -54,6 +56,7 @@
5456
from wlsdeploy.tool.validate.validator import Validator
5557
from wlsdeploy.util import cla_helper
5658
from wlsdeploy.util import cla_utils
59+
from wlsdeploy.util import dictionary_utils
5760
from wlsdeploy.util import env_helper
5861
from wlsdeploy.util import getcreds
5962
from wlsdeploy.util import model_translator
@@ -65,6 +68,30 @@
6568
from wlsdeploy.util.model import Model
6669
from wlsdeploy.util import target_configuration_helper
6770
from wlsdeploy.util import unicode_helper as str_helper
71+
from wlsdeploy.aliases.model_constants import DOMAIN_INFO
72+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_PROPERTY_VALUE
73+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_USER_PROPERTY
74+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_TRUSTSTORE_PROPERTY
75+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_KEYSTORE_PROPERTY
76+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_TRUSTSTORETYPE_PROPERTY
77+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_KEYSTORETYPE_PROPERTY
78+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_TRUSTSTOREPWD_PROPERTY
79+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_KEYSTOREPWD_PROPERTY
80+
from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_NET_TNS_ADMIN
81+
from wlsdeploy.aliases.model_constants import JDBC_SYSTEM_RESOURCE
82+
from wlsdeploy.aliases.model_constants import JDBC_RESOURCE
83+
from wlsdeploy.aliases.model_constants import JDBC_DRIVER_PARAMS
84+
from wlsdeploy.aliases.model_constants import ORACLE_DATABASE_CONNECTION_TYPE
85+
from wlsdeploy.aliases.model_constants import PASSWORD_ENCRYPTED
86+
from wlsdeploy.aliases.model_constants import PROPERTIES
87+
from wlsdeploy.aliases.model_constants import RCU_DB_INFO
88+
from wlsdeploy.aliases.model_constants import RCU_DB_CONN_STRING
89+
from wlsdeploy.aliases.model_constants import RCU_PREFIX
90+
from wlsdeploy.aliases.model_constants import RCU_SCHEMA_PASSWORD
91+
from wlsdeploy.aliases.model_constants import RESOURCES
92+
from wlsdeploy.aliases.model_constants import URL
93+
94+
6895

6996
wlst_helper.wlst_functions = globals()
7097

@@ -101,6 +128,7 @@
101128
CommandLineArgUtil.PASSPHRASE_FILE_SWITCH,
102129
CommandLineArgUtil.PASSPHRASE_PROMPT_SWITCH,
103130
CommandLineArgUtil.DISCOVER_SECURITY_PROVIDER_DATA_SWITCH,
131+
CommandLineArgUtil.DISCOVER_RCU_DATASOURCES_SWITCH,
104132
CommandLineArgUtil.DISCOVER_OPSS_WALLET_SWITCH,
105133
CommandLineArgUtil.OPSS_WALLET_PASSPHRASE_SWITCH,
106134
CommandLineArgUtil.OPSS_WALLET_PASSPHRASE_ENV_SWITCH,
@@ -326,6 +354,8 @@ def __validate_discover_passwords_and_security_data_args(model_context, argument
326354
elif model_context.is_discover_opss_wallet():
327355
# Allow the encryption passphrase
328356
pass
357+
elif model_context.is_discover_rcu_datasources():
358+
pass
329359
elif model_context.get_encryption_passphrase() is not None:
330360
# Don't allow the passphrase arg unless we are discovering passwords or security provider data.
331361
if CommandLineArgUtil.PASSPHRASE_ENV_SWITCH in argument_map:
@@ -394,11 +424,6 @@ def __validate_discover_opss_wallet_args(model_context, argument_map, is_encrypt
394424
_method_name = '__validate_discover_opss_wallet_args'
395425

396426
if CommandLineArgUtil.DISCOVER_OPSS_WALLET_SWITCH in argument_map:
397-
if model_context.get_target_wlst_mode() == WlstModes.OFFLINE:
398-
ex = exception_helper.create_cla_exception(ExitCode.ARG_VALIDATION_ERROR, 'WLSDPLY-06060',_program_name,
399-
CommandLineArgUtil.DISCOVER_OPSS_WALLET_SWITCH)
400-
__logger.throwing(ex, class_name=_class_name, method_name=_method_name)
401-
raise ex
402427

403428
# Cannot verify that JRF is installed because the model_content is not fully
404429
# initialized at this point so the domain typedef is not available.
@@ -727,6 +752,7 @@ def __check_and_customize_model(model, model_context, aliases, credential_inject
727752
__logger.info('WLSDPLY-06014', _class_name=_class_name, method_name=_method_name)
728753

729754
filter_helper.apply_final_filters(model.get_model(), model.get_model(), model_context)
755+
__fix_discovered_template_datasource(model, model_context)
730756

731757
credential_cache = None
732758
if credential_injector is not None:
@@ -764,6 +790,183 @@ def __check_and_customize_model(model, model_context, aliases, credential_inject
764790
__logger.exiting(_class_name, _method_name)
765791
return model
766792

793+
def __fix_discovered_template_datasource(model, model_context):
794+
# fix the case for discovering template datasources.
795+
# If all the template datasources use the dame passwords then generate the RUCDbInfo section
796+
# and remove the template datasources from the model
797+
# If not using the same passwords then do not generate RCUDbinfo, need to go back to fix the password field value
798+
799+
_method_name = '__fix_discovered_template_datasource'
800+
__logger.entering(class_name=_class_name, method_name=_method_name)
801+
802+
domain_typedef = model_context.get_domain_typedef()
803+
if domain_typedef.requires_rcu() and model_context.is_discover_rcu_datasources():
804+
resources = model.get_model_resources()
805+
jdbc_system_resources = dictionary_utils.get_element(resources, JDBC_SYSTEM_RESOURCE)
806+
discover_filters = domain_typedef._discover_filters
807+
filtered_ds_patterns = dictionary_utils.get_element(discover_filters,'/JDBCSystemResource')
808+
passwords = HashSet()
809+
urls = HashSet()
810+
prefixes = HashSet()
811+
properties = __get_urls_and_passwords(model_context, jdbc_system_resources, filtered_ds_patterns,
812+
urls, passwords, prefixes)
813+
if _can_generate_rcudb_info(passwords, urls, prefixes):
814+
__set_rcuinfo_in_model(model, properties, urls[0], passwords[0])
815+
__remove_discovered_template_datasource(jdbc_system_resources, filtered_ds_patterns, model)
816+
__fix_rcudbinfo_passwords(model, model_context, model_context.is_discover_passwords())
817+
else:
818+
__reset_password_to_regular_discovery(jdbc_system_resources, filtered_ds_patterns, model_context)
819+
820+
__logger.exiting(_class_name, _method_name)
821+
822+
def _can_generate_rcudb_info(passwords, urls, prefixes):
823+
return passwords.size() == 1 and urls.size() == 1 and prefixes.size() == 1
824+
825+
def __get_urls_and_passwords(model_context, jdbc_system_resources, filtered_ds_patterns, urls, passwords, prefixes):
826+
properties = None
827+
for item in jdbc_system_resources:
828+
if not __match_filtered_ds_name(item, filtered_ds_patterns):
829+
continue
830+
jdbc_system_resource = jdbc_system_resources[item]
831+
jdbc_resource = dictionary_utils.get_element(jdbc_system_resource, JDBC_RESOURCE)
832+
driver_params = dictionary_utils.get_element(jdbc_resource, JDBC_DRIVER_PARAMS)
833+
properties = dictionary_utils.get_element(driver_params, PROPERTIES)
834+
password_encrypted = dictionary_utils.get_element(driver_params, PASSWORD_ENCRYPTED)
835+
passwords.add(password_encrypted)
836+
schema_user = __get_driver_param_property_value(properties, DRIVER_PARAMS_USER_PROPERTY)
837+
prefix = schema_user[0:schema_user.find('_')]
838+
prefixes.add(prefix)
839+
url = dictionary_utils.get_element(driver_params, URL)
840+
urls.add(url)
841+
842+
return properties
843+
844+
def __set_rcuinfo_in_model(model, properties, url, password_encrypted):
845+
model_dict = model.get_model()
846+
domain_info = dictionary_utils.get_element(model_dict, DOMAIN_INFO)
847+
if domain_info is None:
848+
model_dict[DOMAIN_INFO] = {}
849+
domain_info = model_dict[DOMAIN_INFO]
850+
851+
schema_user = __get_driver_param_property_value(properties, DRIVER_PARAMS_USER_PROPERTY)
852+
853+
domain_info[RCU_DB_INFO] = {}
854+
rcudb_info = domain_info[RCU_DB_INFO]
855+
rcudb_info[RCU_DB_CONN_STRING] = url
856+
857+
rcudb_info[RCU_SCHEMA_PASSWORD] = password_encrypted
858+
prefix = schema_user[0:schema_user.find('_')]
859+
rcudb_info[RCU_PREFIX] = prefix
860+
861+
extra_properties = [DRIVER_PARAMS_TRUSTSTORE_PROPERTY,
862+
DRIVER_PARAMS_KEYSTORE_PROPERTY,
863+
DRIVER_PARAMS_TRUSTSTORETYPE_PROPERTY,
864+
DRIVER_PARAMS_KEYSTORETYPE_PROPERTY,
865+
DRIVER_PARAMS_TRUSTSTOREPWD_PROPERTY,
866+
DRIVER_PARAMS_KEYSTOREPWD_PROPERTY,
867+
DRIVER_PARAMS_NET_TNS_ADMIN
868+
]
869+
870+
for property in extra_properties:
871+
__set_rcu_property_ifnecessary(rcudb_info, properties, property)
872+
873+
874+
# The ORACLE_DATABASE_CONNECTION_TYPE is only used by WDT for processing
875+
atp_tns_alias = __find_atp_tns_alias(url)
876+
if atp_tns_alias is not None:
877+
# This is just based on the observed pattern in tnsnames.ora file for ATP.
878+
# we don't set the actual tns.alias since the url format is subjected to change
879+
rcudb_info[ORACLE_DATABASE_CONNECTION_TYPE] = 'ATP'
880+
elif __test_if_ssl_properties_are_set(properties):
881+
rcudb_info[ORACLE_DATABASE_CONNECTION_TYPE] = 'SSL'
882+
883+
def __test_if_ssl_properties_are_set(properties):
884+
keystore_property = __get_driver_param_property_value(properties, DRIVER_PARAMS_KEYSTORE_PROPERTY)
885+
truststore_property = __get_driver_param_property_value(properties, DRIVER_PARAMS_TRUSTSTORE_PROPERTY)
886+
if keystore_property is not None and truststore_property is not None:
887+
return True
888+
return False
889+
890+
def __find_atp_tns_alias(url):
891+
pattern = r'\(service_name=([a-zA-Z0-9]+)_([a-zA-Z0-9_]+)\.adb\.oraclecloud\.com\)'
892+
match = re.search(pattern, url)
893+
if match:
894+
return match.group(2)
895+
else:
896+
return None
897+
898+
def __set_rcu_property_ifnecessary(rcu_db_info, properties, name):
899+
value = __get_driver_param_property_value(properties, name)
900+
if value is not None:
901+
rcu_db_info[name] = value
902+
903+
def __get_driver_param_property_value(properties, name):
904+
try:
905+
prop = dictionary_utils.get_element(properties, name)
906+
value = dictionary_utils.get_element(prop, DRIVER_PARAMS_PROPERTY_VALUE)
907+
return value
908+
except:
909+
return None
910+
911+
def __remove_discovered_template_datasource(jdbc_system_resources, filtered_ds_patterns, model):
912+
remove_items = []
913+
for item in jdbc_system_resources:
914+
if not __match_filtered_ds_name(item, filtered_ds_patterns):
915+
continue
916+
remove_items.append(item)
917+
918+
for item in remove_items:
919+
del jdbc_system_resources[item]
920+
921+
if len(jdbc_system_resources) == 0:
922+
model_dict = model.get_model()
923+
resources = model_dict[RESOURCES]
924+
del resources[JDBC_SYSTEM_RESOURCE]
925+
if len(resources) == 0:
926+
del model_dict[RESOURCES]
927+
928+
def __reset_password_to_regular_discovery(jdbc_system_resources, filtered_ds_patterns, model_context):
929+
for item in jdbc_system_resources:
930+
if not __match_filtered_ds_name(item, filtered_ds_patterns):
931+
continue
932+
jdbc_system_resource = jdbc_system_resources[item]
933+
jdbc_resource = dictionary_utils.get_element(jdbc_system_resource, JDBC_RESOURCE)
934+
driver_params = dictionary_utils.get_element(jdbc_resource, JDBC_DRIVER_PARAMS)
935+
jdbc_ds_password = driver_params[PASSWORD_ENCRYPTED]
936+
if model_context.is_discover_passwords():
937+
encrypted_model_value = encryption_utils.encrypt_one_password(
938+
model_context.get_encryption_passphrase(), jdbc_ds_password)
939+
driver_params[PASSWORD_ENCRYPTED] = encrypted_model_value
940+
else:
941+
driver_params[PASSWORD_ENCRYPTED] = alias_constants.PASSWORD_TOKEN
942+
return
943+
944+
def __fix_rcudbinfo_passwords(model, model_context, encrypt=False):
945+
946+
model_dict = model.get_model()
947+
rcudb_info = model_dict[DOMAIN_INFO][RCU_DB_INFO]
948+
949+
possible_pwds = [
950+
RCU_SCHEMA_PASSWORD,
951+
DRIVER_PARAMS_TRUSTSTOREPWD_PROPERTY,
952+
DRIVER_PARAMS_KEYSTOREPWD_PROPERTY
953+
]
954+
955+
for item in possible_pwds:
956+
if item in rcudb_info:
957+
if encrypt:
958+
passwd = rcudb_info[item]
959+
rcudb_info[item] = encryption_utils.encrypt_one_password(
960+
model_context.get_encryption_passphrase(), passwd)
961+
else:
962+
rcudb_info[item] = alias_constants.PASSWORD_TOKEN
963+
964+
def __match_filtered_ds_name(name, patterns):
965+
for pattern in patterns:
966+
regex = re.compile(pattern)
967+
if regex.match(name):
968+
return True
969+
return False
767970

768971
def __generate_remote_report_json(model_context):
769972
_method_name = '__remote_report'

core/src/main/python/wlsdeploy/tool/discover/common_resources_discoverer.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,18 @@ def get_datasources(self):
9898
datasources = self._find_names_in_folder(location)
9999
collected_wallet = {}
100100
if datasources is not None:
101-
_logger.info('WLSDPLY-06340', len(datasources), class_name=_class_name, method_name=_method_name)
101+
_logger.info('WLSDPLY-06340', len(datasources), class_name=_class_name,
102+
method_name=_method_name)
102103
typedef = self._model_context.get_domain_typedef()
103104
name_token = self._aliases.get_name_token(location)
104105
for datasource in datasources:
105-
if typedef.is_filtered(location, datasource):
106-
_logger.info('WLSDPLY-06361', typedef.get_domain_type(), datasource, class_name=_class_name,
107-
method_name=_method_name)
106+
if (typedef.is_filtered(location, datasource) and
107+
not self._model_context.is_discover_rcu_datasources()):
108+
_logger.info('WLSDPLY-06361', typedef.get_domain_type(), datasource,
109+
class_name=_class_name, method_name=_method_name)
108110
else:
109-
_logger.info('WLSDPLY-06341', datasource, class_name=_class_name, method_name=_method_name)
111+
_logger.info('WLSDPLY-06341', datasource, class_name=_class_name,
112+
method_name=_method_name)
110113
result[datasource] = OrderedDict()
111114
location.add_name_token(name_token, datasource)
112115
self._populate_model_parameters(result[datasource], location)

core/src/main/python/wlsdeploy/tool/discover/discoverer.py

+26-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from wlsdeploy.aliases import alias_constants
1717
from wlsdeploy.aliases.aliases import Aliases
1818
from wlsdeploy.aliases.location_context import LocationContext
19+
from wlsdeploy.aliases.model_constants import JDBC_SYSTEM_RESOURCE
1920
from wlsdeploy.aliases.model_constants import MASKED_PASSWORD
2021
from wlsdeploy.aliases.wlst_modes import WlstModes
2122
from wlsdeploy.exception import exception_helper
@@ -371,22 +372,39 @@ def _get_model_password_value(self, location, model_name, model_value):
371372
_logger.throwing(ex, class_name=_class_name, method_name=_method_name)
372373
raise ex
373374

374-
base_dir = self._model_context.get_domain_home()
375-
if self._model_context.is_ssh():
376-
base_dir = self.download_temporary_dir
377-
378-
model_value = self._weblogic_helper.decrypt(password_encrypted_string, base_dir)
379-
380-
if self._model_context.is_encrypt_discovered_passwords():
375+
filtered_datasource, model_value = self._get_decrypted_password_and_is_filtered_datasource(location,
376+
password_encrypted_string)
377+
378+
if self._model_context.is_encrypt_discovered_passwords() and not filtered_datasource:
381379
model_value = encryption_utils.encrypt_one_password(
382380
self._model_context.get_encryption_passphrase(), model_value)
383381
else:
384-
model_value = alias_constants.PASSWORD_TOKEN
382+
filtered_datasource, model_value = self._get_decrypted_password_and_is_filtered_datasource(location,
383+
model_value)
384+
temp_clear_pwd = self._model_context.is_discover_rcu_datasources() and filtered_datasource
385+
if not temp_clear_pwd:
386+
model_value = alias_constants.PASSWORD_TOKEN
387+
385388
else:
386389
model_value = None
387390

388391
return model_value
389392

393+
def _get_decrypted_password_and_is_filtered_datasource(self, location, model_value):
394+
# only do it for templated datasource
395+
filtered_datasource = False
396+
model_folders = location.get_model_folders()
397+
if (model_folders[0] == JDBC_SYSTEM_RESOURCE):
398+
loc = LocationContext()
399+
loc.append_location(JDBC_SYSTEM_RESOURCE)
400+
tokens = location.get_name_tokens()
401+
filtered_datasource = self._model_context.get_domain_typedef().is_filtered(loc, tokens['DATASOURCE'])
402+
403+
base_dir = self._model_context.get_domain_home()
404+
if self._model_context.is_ssh():
405+
base_dir = self.download_temporary_dir
406+
return filtered_datasource, self._weblogic_helper.decrypt(model_value, base_dir)
407+
390408
def _get_attributes_for_current_location(self, location):
391409
"""
392410
Change to the mbean folder with the provided name using the current location and return

core/src/main/python/wlsdeploy/tool/discover/opss_wallet_discoverer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def discover(self):
4444
_method_name = 'discover'
4545
_logger.entering(class_name=_class_name, method_name=_method_name)
4646

47-
if self._wlst_mode == WlstModes.OFFLINE or not self._model_context.is_discover_opss_wallet():
47+
if not self._model_context.is_discover_opss_wallet():
4848
_logger.exiting(class_name=_class_name, method_name=_method_name)
4949
return
5050

0 commit comments

Comments
 (0)