diff --git a/README.md b/README.md index 7615d50b49..4e300bb671 100644 --- a/README.md +++ b/README.md @@ -845,6 +845,209 @@ When creating the archive, the tool will try to gather all binaries, scripts, an 1. Any binaries referenced from the `ORACLE_HOME` will not be gathered, as they are assumed to exist in any target domain to which model-driven operations will be applied. Doing this is key to allowing the model to be WebLogic Server version independent. 2. In its current form, the discover domain Tool will only gather binaries and scripts that are accessible from the local machine. Warnings will be generated for any binaries or scripts that cannot be found but the configuration for those binaries will still be collected, where possible. It is the user's responsibility to add those missing files to the archive in the appropriate locations and edit the the model, as needed, to point to those files inside the archive using the relative path inside the archive (for example, `wlsdeploy/applications/myapp.ear`). +## The Variable Injector Tool + +The variable injector tool is used to tokenize a model with variables. The values for these variables are assigned using an external property file. This facilitates using the same domain model to create new domains in different environments. The variable injector tool can be run as an option in the Discover Domain tool, or or from the stand-alone command line interface. + +To enable the Variable Injector during the Discover Domain, create a variable injector configuration by placing a json file named model_variable_injector.json into the \/lib directory using one or more of the pre-defined keywords and/or a CUSTOM list of files. A keyword points to an injector directive file. The tool applies the directives to the attributes in a model, and if the directive matches an attribute, then a property token with a unique variable name is injected into the model and replaces the attribute value. The variable name and model attribute value are placed into the external variable properties file. + +NOTE: Variable injection on an attribute is only performed once. The property token is not replaced by any subsequent matches. + +If variable injection is enabled, the Discover Domain Tool calls the variable injector after the model has been discovered and after all filters run, but before model validation. + +The supported keywords are as follows: + +- CREDENTIALS - All MBean credentials attribute values (user and password) are injected with a variable. + +- HOST - All MBean Host attribute values in the model are injected with a variable. + +- PORT - All MBean Port attribute values in the model are injected with a variable. + +- TARGET - All MBean Target attribute values in the model are injected with a variable. + +- TOPOLOGY - Common environmental MBean attributes found in the topology section of the model are injected with a variable. + This includes server, machine and node manager ports, credentials and listen addresses, and cluster messaging modes, addresses and ports. + +- URL - All MBean URL attribute values in the model are injected with a variable. + +NOTE: The directives used by each pre-defined keyword are defined in an injector json file that is located in the \/lib/injectors folder. These files should not be changed, but could be used as . + +Here is an example of a model_variable_injector.json file using the PORT keyword. + +```json +{ + "PORT": {} +} +``` + +Below is a model snippet that shows injected variables in the port attributes. + +```$yaml + +topology: + Name: soa_domain + AdminServerName: AdminServer + Cluster: + soa_cluster: + osb_cluster: + Server: + AdminServer: + ListenAddress: myadmin.example.com + ListenPort: @@PROP:Server.AdminServer.ListenPort@@ + Machine: machine1 + SSL: + Enabled: true + ListenPort: @@PROP:Server.SSL.AdminServer.ListenPort@@ + soa_server1: + ListenAddress: managed1.example.com + ListenPort: @@PROP:Server.soa_server1.ListenPort@@ + Cluster: soa_cluster + Machine: machine2 + SSL: + Enabled: true + ListenPort: @@PROP:Server.SSL.soa_server1.ListenPort@@ + soa_server2: + ListenAddress: managed2.example.com + ListenPort: @@PROP:Server.soa_server2.ListenPort@@ + Cluster: soa_cluster + Machine: machine3 + SSL: + Enabled: true + ListenPort: @@PROP:Server.SSL.soa_server2.ListenPort@@ +``` + +And the resulting variable property file: + +``` +Server.AdminServer.ListenPort=7001 +Server.AdminServer.SSL.ListenPort=7002 +Server.soa_server1.ListenPort=8001 +Server.soa_server1.SSL.ListenPort=8002 +Server.soa_server2.ListenPort=8001 +Server.soa_server2.SSL.ListenPort=8002 +``` + +To specify the name and location of the variable properties file for the Discover Tool, use the argument `-variable_properties_file` on the command line. Usage of the variable_properties_file argument without the presence of the model variable injector file in the \/lib directory will cause an error condition and the tool will exit. If the model variable injector file exists in the directory, but the command line argument is not used, the variable properties file is created with the following defaults: If the model_file command line argument is used on the Discover Domain run, the properties file name and location will be the same as the model file, with the file extension `.properties`. If only the archive file argument is present, the archive file name and location will be used. + +As with the archive and model file, each run of the discover domain tool will overwrite the contents of an existing variable property file with the values from the current run. + +### Custom Variable Injector + +To designate custom injector directives, use the CUSTOM keyword in the model_variable_injector.json. The CUSTOM keyword requires a a list of one or more custom injector directive json files. + +An injector directive contains a key that identifies an attribute to be tokenized, and an optional set of directive properties. The key is a period separated MBean hierarchy and attribute name as they are defined in the model. Always exclude the name of the model section from the injector key. + +For example, an injector key for the Server SSL Listen Port is as below. This directive contains no additional properties. + +```json +{ + "Server.SSL.ListenPort": {} +} +``` + +NOTE: The hierarchy of MBeans in the model for the ListenPort attribute and note that the MBean name of AdminServer is NOT included in the directive: + +```yaml +topology: + Server: + AdminServer: + ListenAddress: myadmin.example.com + ListenPort: 7001 + Machine: machine1 + SSL: + Enabled: true + ListenPort: 7002 +``` + +These custom injector json files will be processed by the Variable Injector tool before keywords, each file processed in list order. A property injected into an attribute will not be replaced by any subsequent matches. + +#### Custom directive properties + +Include the following properties to refine the directive as specified. + +- force: + If the MBean hierarchy exists in the model, but the attribute does not, then the attribute will be added and persisted to the discovered model. The value stored in the + model is the weblogic default value. + +- variable_value: + Replace the model value with the specified value in the variable properties. This may be used in conjunction with the force directive, replacing the default value with the indicated value. + +- regexp: + A list of regexp patterns that will be applied to either the string values or map values of an attribute in the model. If the pattern matches, then the matching part of the + string or dictionary will be injected with a property token and a unique variable name . +-- pattern: + the regular expression pattern to apply to the string value or map values of an attribute +-- suffix: + The suffix name to append to each resulting variable name in order to create a unique variable name + +The regexp list is useful when only a segment of a string value or map needs to be tokenized (giving you a clean list of property values in the variable properties file). You can inject more than one token into a string or map with multiple patterns. However, when you have more than one pattern, you must provide a suffix for each. This allows the tool to generate a unique variable name for each token in the string or map. + +The following is an example of how to effectively use the regexp directive list to search for a segment in a string value. In this example, we want to search for the host and port in each Oracle JDBC URL that uses the special Oracle URL notation, and create an entry for the host and port in the variable properties file. + +In the model, we expect to find a URL like the following: + +```$yaml + JDBCSystemResource: + Database1: + JdbcResource: + JDBCDriverParams: + URL: 'jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=slc05til.us.oracle.com)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl.us.oracle.com)))' +``` + +We create a directive in our custom injector json file: + +```json + "JDBCSystemResource.JdbcResource.JDBCDriverParams.URL": + { + "regexp": [ + { + "pattern": "(?<=PORT=)[\\w.-]+(?=\\))", + "suffix": "Port" + }, + { + "pattern": "(?<=HOST=)[\\w.-]+(?=\\))", + "suffix": "Host" + } + ] + }, +``` + +During the Discover Domain tool run, the pattern is applied to the URL string and tokens injected into the string: + +``` +URL: 'jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=@@PROP:JDBCSystemResource.Database1.JdbcResource.JDBCDriverParams.URL--Host@@:)(PORT=@@PROP:JDBCSystemResource.Database1.JdbcResource.JDBCDriverParams.URL--Port@@)))(CONNECT_DATA=(SERVICE_NAME=orcl.us.oracle.com)))' +``` + +And The variables put in the properties file: + +``` +JDBCSystemResource.Database1.JdbcResource.JDBCDriverParams.URL--Host=slc05til.us.oracle.com +JDBCSystemResource.Database1.JdbcResource.JDBCDriverParams.URL--Port=1521 +``` + +#### Selecting specific MBean names for variable injection + +This final custom directive allows you to explicitly define which named entries for an MBean in the model you wish to inject properties. For instance, you might wish to tokenize an attribute just for a specific server. To define a list of one or more names for a specific MBean in the injector directive hierarchy, format the list as follows: +``` +MBean[comma separated list of names] +`` +To select only the admin server named AdminServer for a Server directive, use the format Server[AdminServer]. To select servers soa_server1 and soa_server2, format the key as Server[soa_server1,soa_server2] + +The injector tool recognizes two KEYWORDS for a user list, MANAGED_SERVERS (all the managed servers in the model) and ADMIN_SERVER (The admin server in the model). + +A custom injector for the admin server SSL listen port is: + +```json +{ + "Server[ADMIN_SERVER].SSL.ListenPort": {}, +} +``` + +## Samples + +A sample of a model_variable_injector.json file and a custom injector json file are installed in the WLSDEPLOY/samples directory. + + ## Downloading and Installing the Software The Oracle WebLogic Server Deploy Tooling project repository is located at [`https://github.com/oracle/weblogic-deploy-tooling`](https://github.com/oracle/weblogic-deploy-tooling). Binary distributions of the `weblogic-deploy.zip` installer can be downloaded from the [GitHub Releases page](https://github.com/oracle/weblogic-deploy-tooling/releases). To install the software, simply unzip the `weblogic-deploy.zip` installer on a machine that has the desired versions of WebLogic Server installed. After being unzipped, the software is ready to use, just set the `JAVA_HOME` environment variable to point to a Java 7 or higher JDK and the shell scripts are ready to run. diff --git a/core/src/main/python/discover.py b/core/src/main/python/discover.py index 675374bf76..07580c5504 100644 --- a/core/src/main/python/discover.py +++ b/core/src/main/python/discover.py @@ -12,20 +12,20 @@ from java.lang import IllegalArgumentException from java.lang import IllegalStateException from java.lang import String - from oracle.weblogic.deploy.aliases import AliasException from oracle.weblogic.deploy.discover import DiscoverException from oracle.weblogic.deploy.util import CLAException from oracle.weblogic.deploy.util import FileUtils from oracle.weblogic.deploy.util import PyWLSTException from oracle.weblogic.deploy.util import TranslateException -from oracle.weblogic.deploy.util import WebLogicDeployToolingVersion from oracle.weblogic.deploy.util import WLSDeployArchive from oracle.weblogic.deploy.util import WLSDeployArchiveIOException +from oracle.weblogic.deploy.util import WebLogicDeployToolingVersion from oracle.weblogic.deploy.validate import ValidateException sys.path.append(os.path.dirname(os.path.realpath(sys.argv[0]))) +import wlsdeploy.tool.util.variable_injector as variable_injector from wlsdeploy.aliases.wlst_modes import WlstModes from wlsdeploy.exception import exception_helper from wlsdeploy.logging.platform_logger import PlatformLogger @@ -36,8 +36,9 @@ from wlsdeploy.tool.discover.multi_tenant_discoverer import MultiTenantDiscoverer from wlsdeploy.tool.discover.resources_discoverer import ResourcesDiscoverer from wlsdeploy.tool.discover.topology_discoverer import TopologyDiscoverer -from wlsdeploy.tool.validate.validator import Validator from wlsdeploy.tool.util import filter_helper +from wlsdeploy.tool.util.variable_injector import VariableInjector +from wlsdeploy.tool.validate.validator import Validator from wlsdeploy.util import wlst_helper from wlsdeploy.util import model_translator from wlsdeploy.util.cla_utils import CommandLineArgUtil @@ -58,8 +59,9 @@ __optional_arguments = [ # Used by shell script to locate WLST - CommandLineArgUtil.DOMAIN_TYPE_SWITCH, CommandLineArgUtil.MODEL_FILE_SWITCH, + CommandLineArgUtil.DOMAIN_TYPE_SWITCH, + CommandLineArgUtil.VARIABLE_PROPERTIES_FILE_SWITCH, CommandLineArgUtil.ADMIN_URL_SWITCH, CommandLineArgUtil.ADMIN_USER_SWITCH, CommandLineArgUtil.ADMIN_PASS_SWITCH @@ -80,6 +82,7 @@ def __process_args(args): __verify_required_args_present(required_arg_map) __wlst_mode = __process_online_args(optional_arg_map) __process_archive_filename_arg(required_arg_map) + __process_variable_filename_arg(optional_arg_map) combined_arg_map = optional_arg_map.copy() combined_arg_map.update(required_arg_map) @@ -135,7 +138,7 @@ def __process_online_args(optional_arg_map): raise ex optional_arg_map[CommandLineArgUtil.ADMIN_PASS_SWITCH] = String(password) - __logger.info('WLSDPLY-06020') + __logger.info('WLSDPLY-06020', class_name=_class_name, method_name=_method_name) return mode @@ -159,6 +162,28 @@ def __process_archive_filename_arg(required_arg_map): return +def __process_variable_filename_arg(optional_arg_map): + """ + If the variable filename argument is present, the required model variable injector json file must exist in + the WLSDEPLOY lib directory. + :param optional_arg_map: containing the variable file name + :raises: CLAException: if this argument is present but the model variable injector json does not exist + """ + _method_name = '__process_variable_filename_arg' + + if CommandLineArgUtil.VARIABLE_PROPERTIES_FILE_SWITCH in optional_arg_map: + variable_injector_file_name = variable_injector.get_default_variable_injector_file_name() + try: + FileUtils.validateExistingFile(variable_injector_file_name) + except IllegalArgumentException, ie: + ex = exception_helper.create_cla_exception('WLSDPLY-06021', optional_arg_map[ + CommandLineArgUtil.VARIABLE_PROPERTIES_FILE_SWITCH], variable_injector_file_name, + ie.getLocalizedMessage(), error=ie) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + return + + def __discover(model_context): """ Populate the model from the domain. @@ -344,7 +369,7 @@ def __persist_model(model, model_context): if not model_file.delete(): model_file.deleteOnExit() except (WLSDeployArchiveIOException, IllegalArgumentException), arch_ex: - ex = exception_helper.create_discover_exception('WLSDPLY-06009', model_file.getAbsolutePath(), + ex = exception_helper.create_discover_exception('WLSDPLY-20023', model_file.getAbsolutePath(), model_file_name, arch_ex.getLocalizedMessage(), error=arch_ex) __logger.throwing(ex, class_name=_class_name, method_name=_method_name) @@ -368,25 +393,31 @@ def __check_and_customize_model(model, model_context): if filter_helper.apply_filters(model.get_model(), "discover"): __logger.info('WLSDPLY-06014', _class_name=_class_name, method_name=_method_name) - + inserted, variable_model, variable_file_name = VariableInjector(_program_name, model.get_model(), model_context, + WebLogicHelper( + __logger).get_actual_weblogic_version()).\ + inject_variables_keyword_file() + if inserted: + model = Model(variable_model) try: validator = Validator(model_context, wlst_mode=__wlst_mode) # no variables are generated by the discover tool - validator.validate_in_tool_mode(model.get_model(), variables_file_name=None, - archive_file_name=model_context.get_archive_file_name()) + validator.validate_in_tool_mode(model.get_model(), variables_file_name=variable_file_name, + archive_file_name=model_context.get_archive_file_name()) except ValidateException, ex: __logger.warning('WLSDPLY-06015', ex.getLocalizedMessage(), class_name=_class_name, method_name=_method_name) + return model -def __log_and_exit(exit_code, _class_name, _method_name): +def __log_and_exit(exit_code, class_name, _method_name): """ Helper method to log the exiting message and call sys.exit() :param exit_code: the exit code to use - :param _class_name: the class name to pass to the logger + :param class_name: the class name to pass to the logger :param _method_name: the method name to pass to the logger """ - __logger.exiting(result=exit_code, class_name=_class_name, method_name=_method_name) + __logger.exiting(result=exit_code, class_name=class_name, method_name=_method_name) sys.exit(exit_code) @@ -433,12 +464,12 @@ def main(args): error=ex, class_name=_class_name, method_name=_method_name) __log_and_exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE, _class_name, _method_name) - __check_and_customize_model(model, model_context) - + model = __check_and_customize_model(model, model_context) try: __persist_model(model, model_context) + except TranslateException, ex: - __logger.severe('WLSDPLY-06012', _program_name, model_context.get_archive_file_name(), ex.getLocalizedMessage(), + __logger.severe('WLSDPLY-20024', _program_name, model_context.get_archive_file_name(), ex.getLocalizedMessage(), error=ex, class_name=_class_name, method_name=_method_name) __log_and_exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE, _class_name, _method_name) diff --git a/core/src/main/python/encrypt.py b/core/src/main/python/encrypt.py index 03cc3240c4..4f306f7365 100644 --- a/core/src/main/python/encrypt.py +++ b/core/src/main/python/encrypt.py @@ -190,7 +190,7 @@ def __encrypt_model_and_variables(model_context): if variable_change_count > 0: try: - variable_helper.write_variables(variables, variable_file) + variable_helper.write_variables(_program_name, variables, variable_file) __logger.info('WLSDPLY-04209', _program_name, variable_change_count, variable_file, class_name=_class_name, method_name=_method_name) except VariableException, ve: diff --git a/core/src/main/python/variable_inject.py b/core/src/main/python/variable_inject.py new file mode 100644 index 0000000000..4edeaab9ac --- /dev/null +++ b/core/src/main/python/variable_inject.py @@ -0,0 +1,315 @@ +""" +Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 + +The entry point for the discoverDomain tool. +""" +import os +import sys + +from java.io import File +from java.lang import IllegalArgumentException +from java.lang import IllegalStateException +from oracle.weblogic.deploy.util import CLAException +from oracle.weblogic.deploy.util import FileUtils +from oracle.weblogic.deploy.util import TranslateException +from oracle.weblogic.deploy.util import WLSDeployArchive +from oracle.weblogic.deploy.util import WLSDeployArchiveIOException +from oracle.weblogic.deploy.util import WebLogicDeployToolingVersion + + +sys.path.append(os.path.dirname(os.path.realpath(sys.argv[0]))) + +import wlsdeploy.tool.util.variable_injector as variable_injector +from wlsdeploy.aliases.wlst_modes import WlstModes +from wlsdeploy.exception import exception_helper +from wlsdeploy.logging.platform_logger import PlatformLogger +from wlsdeploy.tool.util.variable_injector import VariableInjector +from wlsdeploy.util import wlst_helper +from wlsdeploy.util import model_translator +from wlsdeploy.util.cla_utils import CommandLineArgUtil +from wlsdeploy.util.model import Model +from wlsdeploy.util.model_context import ModelContext +from wlsdeploy.util.model_translator import FileToPython +from wlsdeploy.util.weblogic_helper import WebLogicHelper + +_program_name = 'injectVariables' +_class_name = 'variable_inject' +__logger = PlatformLogger('wlsdeploy.tool.util') +__wlst_mode = WlstModes.OFFLINE +__kwargs = dict() +__inserted = False +__tmp_model_dir = None + +__required_arguments = [ + CommandLineArgUtil.ORACLE_HOME_SWITCH +] + +__optional_arguments = [ + CommandLineArgUtil.MODEL_FILE_SWITCH, + CommandLineArgUtil.ARCHIVE_FILE_SWITCH, + CommandLineArgUtil.VARIABLE_INJECTOR_FILE_SWITCH, + CommandLineArgUtil.VARIABLE_KEYWORDS_FILE_SWITCH, + CommandLineArgUtil.VARIABLE_PROPERTIES_FILE_SWITCH, + CommandLineArgUtil.DOMAIN_TYPE_SWITCH +] + + +def __process_args(args): + """ + Process the command-line arguments and prompt the user for any missing information + :param args: the command-line arguments list + :raises CLAException: if an error occurs while validating and processing the command-line arguments + """ + global __wlst_mode + + cla_util = CommandLineArgUtil(_program_name, __required_arguments, __optional_arguments) + required_arg_map, optional_arg_map = cla_util.process_args(args) + + __process_model_args(optional_arg_map) + __process_injector_file(optional_arg_map) + __process_keywords_file(optional_arg_map) + __process_properties_file(optional_arg_map) + + combined_arg_map = optional_arg_map.copy() + combined_arg_map.update(required_arg_map) + + return ModelContext(_program_name, combined_arg_map) + + +def __verify_required_args_present(required_arg_map): + """ + Verify that the required args are present. + :param required_arg_map: the required arguments map + :raises CLAException: if one or more of the required arguments are missing + """ + _method_name = '__verify_required_args_present' + + for req_arg in __required_arguments: + if req_arg not in required_arg_map: + ex = exception_helper.create_cla_exception('WLSDPLY-20005', _program_name, req_arg) + ex.setExitCode(CommandLineArgUtil.USAGE_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + return + + +def __process_model_args(optional_arg_map): + """ + Verify that either the model_file or archive_file was provided and exists. + If the model_file was not provided, the archive_file must be provided and the indicated archive file + must contain a model file. Extract the model file if the archive_file was provided. + :param optional_arg_map: the optional arguments map + :raises CLAException: if the arguments are invalid or an error occurs extracting the model from the archive + """ + _method_name = '__process_model_args' + global __tmp_model_dir + + if CommandLineArgUtil.MODEL_FILE_SWITCH in optional_arg_map: + model_file_name = optional_arg_map[CommandLineArgUtil.MODEL_FILE_SWITCH] + + try: + FileUtils.validateExistingFile(model_file_name) + except IllegalArgumentException, iae: + ex = exception_helper.create_cla_exception('WLSDPLY-20006', _program_name, model_file_name, + iae.getLocalizedMessage(), error=iae) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + elif CommandLineArgUtil.ARCHIVE_FILE_SWITCH in optional_arg_map: + archive_file_name = optional_arg_map[CommandLineArgUtil.ARCHIVE_FILE_SWITCH] + + try: + archive_file = WLSDeployArchive(archive_file_name) + contains_model = archive_file.containsModel() + if not contains_model: + ex = exception_helper.create_cla_exception('WLSDPLY-19603', archive_file_name) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + else: + __tmp_model_dir = FileUtils.createTempDirectory(_program_name) + tmp_model_file = \ + FileUtils.fixupFileSeparatorsForJython(archive_file.extractModel(__tmp_model_dir).getAbsolutePath()) + except (IllegalArgumentException, IllegalStateException, WLSDeployArchiveIOException), archex: + ex = exception_helper.create_cla_exception('WLSDPLY-20010', _program_name, archive_file_name, + archex.getLocalizedMessage(), error=archex) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + optional_arg_map[CommandLineArgUtil.MODEL_FILE_SWITCH] = FileUtils.fixupFileSeparatorsForJython(tmp_model_file) + else: + ex = exception_helper.create_cla_exception('WLSDPLY-20015', _program_name, CommandLineArgUtil.MODEL_FILE_SWITCH, + CommandLineArgUtil.ARCHIVE_FILE_SWITCH) + ex.setExitCode(CommandLineArgUtil.USAGE_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + return + + +def __process_injector_file(optional_arg_map): + _method_name = '__process_injector_file' + if CommandLineArgUtil.VARIABLE_INJECTOR_FILE_SWITCH in optional_arg_map: + injector = optional_arg_map[CommandLineArgUtil.VARIABLE_INJECTOR_FILE_SWITCH] + __logger.fine('WLSDPLY-19600', injector, class_name=_class_name, method_name=_method_name) + __kwargs[variable_injector.VARIABLE_INJECTOR_FILE_NAME_ARG] = injector + + +def __process_keywords_file(optional_arg_map): + _method_name = '__process_keywords_file' + if CommandLineArgUtil.VARIABLE_KEYWORDS_FILE_SWITCH in optional_arg_map: + keywords = optional_arg_map[CommandLineArgUtil.VARIABLE_KEYWORDS_FILE_SWITCH] + __logger.fine('WLSDPLY-19601', keywords, class_name=_class_name, method_name=_method_name) + __kwargs[variable_injector.VARIABLE_KEYWORDS_FILE_NAME_ARG] = keywords + + +def __process_properties_file(optional_arg_map): + _method_name = '__process_properties_file' + if CommandLineArgUtil.VARIABLE_PROPERTIES_FILE_SWITCH in optional_arg_map: + properties = optional_arg_map[CommandLineArgUtil.VARIABLE_PROPERTIES_FILE_SWITCH] + __logger.fine('WLSDPLY-19602', properties, class_name=_class_name, method_name=_method_name) + __kwargs[variable_injector.VARIABLE_FILE_NAME_ARG] = properties + + +def __inject(model, model_context): + """ + Inject variables into the model file that is loaded into the model_context. + :param model_context: the model context + :return: True if variables were inserted into model: The updated model + """ + __kwargs[variable_injector.VARIABLE_FILE_APPEND_ARG] = variable_injector.VARIABLE_FILE_UPDATE + inserted, variable_model, variable_file_name = VariableInjector(_program_name, model, model_context, + WebLogicHelper( + __logger).get_actual_weblogic_version()). \ + inject_variables_keyword_file(**__kwargs) + if inserted: + model = Model(variable_model) + return inserted, model + + +def __close_archive(model_context): + """ + Close the archive object + :param model_context: the model context + """ + _method_name = '__close_archive' + + __logger.entering(_class_name=_class_name, method_name=_method_name) + archive_file = model_context.get_archive_file() + if archive_file: + archive_file.close() + __logger.exiting(class_name=_class_name, method_name=_method_name) + return + + +def __persist_model(model, model_context): + """ + Save the model to the specified model file name or to the archive if the file name was not specified. + :param model: the model to save + :param model_context: the model context + :raises DiscoverException: if an error occurs while create a temporary file for the model + or while adding it to the archive + :raises TranslateException: if an error occurs while serializing the model or writing it to disk + """ + _method_name = '__persist_model' + + __logger.entering(class_name=_class_name, method_name=_method_name) + + add_to_archive = False + model_file_name = model_context.get_model_file() + model_file = FileUtils.getCanonicalFile(File(model_file_name)) + if model_file_name is None: + add_to_archive = True + try: + model_translator.PythonToFile(model.get_model()).write_to_file(model_file.getAbsolutePath()) + except TranslateException, ex: + # Jython 2.2.1 does not support finally so use this like a finally block... + if add_to_archive and not model_file.delete(): + model_file.deleteOnExit() + raise ex + + if add_to_archive: + try: + archive_file = model_context.get_archive_file() + archive_file.addModel(model_file, model_file_name) + if not model_file.delete(): + model_file.deleteOnExit() + except (WLSDeployArchiveIOException, IllegalArgumentException), arch_ex: + ex = exception_helper.create_discover_exception('WLSDPLY-20023', _program_name, + model_file.getAbsolutePath(), model_file_name, + arch_ex.getLocalizedMessage(), + error=arch_ex) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + if not model_file.delete(): + model_file.deleteOnExit() + raise ex + + __logger.exiting(class_name=_class_name, method_name=_method_name) + return + + +def __log_and_exit(exit_code, class_name, _method_name): + """ + Helper method to log the exiting message and call sys.exit() + :param exit_code: the exit code to use + :param class_name: the class name to pass to the logger + :param _method_name: the method name to pass to the logger + """ + __logger.exiting(result=exit_code, class_name=class_name, method_name=_method_name) + sys.exit(exit_code) + + +def main(args): + """ + The main entry point for the discoverDomain tool. + + :param args: + :return: + """ + _method_name = 'main' + + __logger.entering(class_name=_class_name, method_name=_method_name) + for index, arg in enumerate(args): + __logger.finer('sys.argv[{0}] = {1}', str(index), str(arg), class_name=_class_name, method_name=_method_name) + + wlst_helper.silence() + + exit_code = CommandLineArgUtil.PROG_OK_EXIT_CODE + + model_context = None + try: + model_context = __process_args(args) + except CLAException, ex: + exit_code = ex.getExitCode() + if exit_code != CommandLineArgUtil.HELP_EXIT_CODE: + __logger.severe('WLSDPLY-20008', _program_name, ex.getLocalizedMessage(), error=ex, + class_name=_class_name, method_name=_method_name) + __log_and_exit(exit_code, _class_name, _method_name) + + model_file = model_context.get_model_file() + try: + model = FileToPython(model_file, True).parse() + except TranslateException, te: + __logger.severe('WLSDPLY-20009', _program_name, model_file, te.getLocalizedMessage(), error=te, + class_name=_class_name, method_name=_method_name) + sys.exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE) + + inserted, model = __inject(model, model_context) + if inserted: + __logger.info('WLSDPLY-19604', class_name=_class_name, method_name=_method_name) + try: + __persist_model(model, model_context) + + except TranslateException, ex: + __logger.severe('WLSDPLY-20024', _program_name, model_context.get_archive_file_name(), + ex.getLocalizedMessage(), error=ex, class_name=_class_name, method_name=_method_name) + __log_and_exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE, _class_name, _method_name) + + __close_archive(model_context) + + __logger.exiting(result=exit_code, class_name=_class_name, method_name=_method_name) + sys.exit(exit_code) + +if __name__ == 'main': + WebLogicDeployToolingVersion.logVersionInfo(_program_name) + main(sys.argv) diff --git a/core/src/main/python/wlsdeploy/tool/util/variable_injector.py b/core/src/main/python/wlsdeploy/tool/util/variable_injector.py new file mode 100644 index 0000000000..1031b1ce07 --- /dev/null +++ b/core/src/main/python/wlsdeploy/tool/util/variable_injector.py @@ -0,0 +1,778 @@ +""" +Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 +""" +import copy +import os +import re + +import java.lang.Boolean as Boolean +import java.lang.IllegalArgumentException as IllegalArgumentException + +import oracle.weblogic.deploy.aliases.AliasException as AliasException +import oracle.weblogic.deploy.json.JsonException as JsonException +import oracle.weblogic.deploy.util.VariableException as VariableException + +import wlsdeploy.tool.util.variable_injector_functions as variable_injector_functions +import wlsdeploy.util.model as model_sections +import wlsdeploy.util.variables as variables +from wlsdeploy.aliases.aliases import Aliases +from wlsdeploy.aliases.location_context import LocationContext +from wlsdeploy.aliases.wlst_modes import WlstModes +from wlsdeploy.aliases.validation_codes import ValidationCodes +from wlsdeploy.json.json_translator import JsonToPython +from wlsdeploy.logging.platform_logger import PlatformLogger + +WEBLOGIC_DEPLOY_HOME_TOKEN = '@@WLSDEPLOY@@' + +# KWARGS to modify how files are found and loaded on the inject_variables_keyword_file(..) function +VARIABLE_INJECTOR_FILE_NAME = 'model_variable_injector.json' +VARIABLE_KEYWORDS_FILE_NAME = 'variable_keywords.json' +VARIABLE_INJECTOR_PATH_NAME_ARG = 'variable_injector_path_name' +VARIABLE_KEYWORDS_PATH_NAME_ARG = 'variable_keywords_path_name' +VARIABLE_INJECTOR_FILE_NAME_ARG = 'variable_injector_file_name' +VARIABLE_KEYWORDS_FILE_NAME_ARG = 'variable_keywords_file_name' +VARIABLE_INJECTOR_FILES_PATH_ARG = 'variable_injector_files_path_name' +VARIABLE_FILE_NAME_ARG = 'variable_file_name' +VARIABLE_FILE_NAME = 'variable.properties' +VARIABLE_FILE_APPEND_ARG = 'append_to_variables' +VARIABLE_FILE_APPEND = 'append' +VARIABLE_FILE_UPDATE = 'update' +VARIABLE_FILE_APPEND_VALS = [VARIABLE_FILE_APPEND, VARIABLE_FILE_UPDATE] + + +# custom keyword in model injector file +CUSTOM_KEYWORD = 'CUSTOM' +KEYWORD_FILES = 'file-list' +# location for model injector file, keyword file and injector files +DEFAULT_FILE_LOCATION = 'lib' +INJECTORS_LOCATION = 'injectors' +# should these injector json keywords be included in the keyword file +REGEXP = 'regexp' +REGEXP_SUFFIX = 'suffix' +REGEXP_PATTERN = 'pattern' +FORCE = 'force' +VARIABLE_VALUE = 'variable_value' + +VARIABLE_SEP = '.' +SUFFIX_SEP = '--' + +MANAGED_SERVERS = 'MANAGED_SERVERS' +ADMIN_SERVER = 'ADMIN_SERVER' + +# This could be changed into a loaded file so that others can add their own bits of code to +# selectively identify which names in an mbean list should be injected with properties +USER_KEYWORD_DICT = { + MANAGED_SERVERS: 'managed_server_list', + ADMIN_SERVER: 'admin_server_list' +} +# global variables for functions in VariableInjector +_find_special_names_pattern = re.compile('[\[\]]') +_fake_name_marker = 'fakename' +_fake_name_replacement = re.compile('.' + _fake_name_marker) +_white_space_replacement = re.compile('\s') +_split_around_special_names = re.compile('([\w]+\[[\w\.,]+\])|\.') + +_wlsdeploy_location = os.environ.get('WLSDEPLOY_HOME') +_class_name = 'variable_injector' +_logger = PlatformLogger('wlsdeploy.tool.util') + + +class VariableInjector(object): + + def __init__(self, program_name, model, model_context=None, version=None): + """ + Construct an instance of the injector with the model and information used by the injector. + :param program_name: name of the calling tool + :param model: to be updated with variables + :param model_context: context with command line information + :param version: of model if model context is not provided + """ + self.__program_name = program_name + self.__original = copy.deepcopy(model) + self.__model = model + self.__model_context = model_context + if self.__model_context: + self.__wlst_mode = self.__model_context.get_target_wlst_mode() + else: + self.__wlst_mode = WlstModes.OFFLINE + self.__section_keys = model_sections.get_model_top_level_keys() + self.__section_keys.remove(model_sections.get_model_domain_info_key()) + + if version: + self.__aliases = Aliases(model_context, self.__wlst_mode, version, None) + else: + self.__aliases = Aliases(model_context) + + def inject_variables_keyword_file(self, **kwargs): + """ + Replace attribute values with variables and generate a variable dictionary. + The variable replacement is driven from the values in the model variable helper file. + This file can either contain the name of a replacement file, or a list of pre-defined + keywords for canned replacement files. + Return the variable dictionary with the variable name inserted into the model, and the value + that the inserted variable replaced. + :param kwargs: arguments used to override default for variable processing, typically used in test situations + :return: variable dictionary containing + """ + _method_name = 'inject_variables_keyword_file' + _logger.entering(class_name=_class_name, method_name=_method_name) + + variable_injector_location_file = _get_variable_injector_file_name(**kwargs) + variables_injector_dictionary = _load_variable_injector_file(variable_injector_location_file) + variable_keywords_location_file = _get_variable_keywords_file_name(**kwargs) + keywords_dictionary = _load_keywords_file(variable_keywords_location_file) + + variables_inserted = False + return_model = self.__original + variable_file_location = None + if variables_injector_dictionary and keywords_dictionary: + variable_file_location = self._get_variable_file_name(**kwargs) + if not variable_file_location: + _logger.warning('WLSDPLY-19520', variable_injector_location_file, class_name=_class_name, + method_name=_method_name) + else: + _logger.info('WLSDPLY-19533', variable_injector_location_file, class_name=_class_name, + method_name=_method_name) + append, stage_dictionary = _load_variable_file(variable_file_location, **kwargs) + injector_file_list = _create_injector_file_list(variables_injector_dictionary, keywords_dictionary, + _get_keyword_files_location(**kwargs)) + variables_file_dictionary = self.inject_variables_keyword_dictionary(injector_file_list) + if variables_file_dictionary: + stage_dictionary.update(variables_file_dictionary) + variables_inserted = self._write_variables_file(stage_dictionary, variable_file_location, + append) + if variables_inserted: + _logger.info('WLSDPLY-19518', variable_file_location, class_name=_class_name, + method_name=_method_name) + return_model = self.__model + else: + _logger.info('WLSDPLY-19519', class_name=_class_name, method_name=_method_name) + variable_file_location = None + else: + _logger.info('WLSDPLY-19532', variable_injector_location_file, class_name=_class_name, + method_name=_method_name) + + _logger.exiting(class_name=_class_name, method_name=_method_name, result=variables_inserted) + return variables_inserted, return_model, variable_file_location + + def inject_variables_keyword_dictionary(self, injector_file_list): + """ + Takes a variable keyword dictionary and returns a variables for file in a dictionary + :param injector_file_list: list of injector files for processing variable injection + :return: variables_dictionary containing the variable properties to persist to the variable file + """ + _method_name = 'inject_variables_keyword_dictionary' + _logger.entering(injector_file_list, class_name=_class_name, method_name=_method_name) + variable_dictionary = dict() + for filename in injector_file_list: + injector_dictionary = _load_injector_file(self._replace_tokens(filename)) + entries = self.inject_variables(injector_dictionary) + if entries: + _logger.finer('WLSDPLY-19513', filename, class_name=_class_name, method_name=_method_name) + variable_dictionary.update(entries) + _logger.exiting(class_name=_class_name, method_name=_method_name, result=variable_dictionary) + return variable_dictionary + + def inject_variables(self, injector_dictionary): + """ + Iterate through the injector dictionary that was loaded from the file for the model + injector file keyword. + :param injector_dictionary: + :return: variable dictionary containing the variable string and model value entries + """ + variable_dict = dict() + if injector_dictionary: + location = LocationContext() + domain_token = self.__aliases.get_name_token(location) + location.add_name_token(domain_token, _fake_name_marker) + for injector, injector_values in injector_dictionary.iteritems(): + entries_dict = self.__inject_variable(location, injector, injector_values) + if len(entries_dict) > 0: + variable_dict.update(entries_dict) + + return variable_dict + + def __inject_variable(self, location, injector, injector_values): + _method_name = '__inject_variable' + _logger.entering(injector, class_name=_class_name, method_name=_method_name) + variable_dict = dict() + start_mbean_list, attribute = _split_injector(injector) + + def _traverse_variables(model_section, mbean_list): + if mbean_list: + mbean = mbean_list.pop(0) + mbean, mbean_name_list = self._find_special_name(mbean) + _logger.finer('WLSDPLY-19523', mbean, location.get_folder_path(), class_name=_class_name, + method_name=_method_name) + if mbean in model_section: + _logger.finest('WLSDPLY-19514', mbean, class_name=_class_name, method_name=_method_name) + next_model_section = model_section[mbean] + location.append_location(mbean) + name_token = self.__aliases.get_name_token(location) + if not mbean_name_list: + if self.__aliases.supports_multiple_mbean_instances(location): + mbean_name_list = next_model_section + else: + self._check_name_token(location, name_token) + else: + _logger.fine('WLSDPLY-19506', mbean_name_list, attribute, location.get_folder_path(), + class_name=_class_name, method_name=_method_name) + if mbean_name_list: + for mbean_name in mbean_name_list: + if mbean_name in next_model_section: + continue_mbean_list = copy.copy(mbean_list) + location.add_name_token(name_token, mbean_name) + _traverse_variables(next_model_section[mbean_name], continue_mbean_list) + location.remove_name_token(name_token) + else: + _traverse_variables(next_model_section, mbean_list) + location.pop_location() + else: + self._log_mbean_not_found(mbean, injector, location) + return False + else: + self._check_insert_attribute_model(location, model_section, attribute, injector_values) + if attribute in model_section: + returned_dict = self._variable_info(model_section, attribute, location, injector_values) + if returned_dict: + variable_dict.update(returned_dict) + else: + _logger.finer('WLSDPLY-19517', attribute, injector, location.get_folder_path(), + class_name=_class_name, method_name=_method_name) + return True + + section = self.__model + if start_mbean_list: + # Find out in what section is the mbean top folder so can move to that section in the model + top_mbean, __ = self._find_special_name(start_mbean_list[0]) + for entry in self.__section_keys: + if entry in self.__model and top_mbean in self.__model[entry]: + section = self.__model[entry] + break + else: + # This is a domain attribute + section = self.__model[model_sections.get_model_topology_key()] + # if it wasn't found, will log appropriately in the called method + # This also will allow someone to put the section in the injector string + _traverse_variables(section, start_mbean_list) + + _logger.exiting(class_name=_class_name, method_name=_method_name, result=variable_dict) + + return variable_dict + + def __format_variable_name(self, location, attribute): + _method_name = '__format_variable_name' + variable_name = attribute + make_path = None + try: + make_path = self.__aliases.get_model_folder_path(location) + except AliasException, ae: + _logger.warning('WLSDPLY-19531', str(location), attribute, ae.getLocalizedMessage(), class_name=_class_name, + method_name=_method_name) + if make_path: + make_path = make_path.split(':') + if len(make_path) > 1 and len(make_path[1]) > 1: + variable_name = make_path[1] + variable_name = variable_name[1:] + VARIABLE_SEP + attribute + return _massage_name(variable_name) + + def __format_variable_name_segment(self, location, attribute, suffix): + path = self.__format_variable_name(location, attribute) + if suffix: + return path + SUFFIX_SEP + suffix + return path + + def _variable_info(self, model, attribute, location, injector_values): + # add code here to put in model if force in injector values + if REGEXP in injector_values: + return self._process_regexp(model, attribute, location, injector_values) + else: + return self._process_attribute(model, attribute, location, injector_values) + + def _process_attribute(self, model, attribute, location, injector_values): + _method_name = '_process_attribute' + _logger.entering(attribute, location.get_folder_path(), class_name=_class_name, + method_name=_method_name) + variable_dict = dict() + variable_name = None + variable_value = None + attribute_value = model[attribute] + if not _already_property(attribute_value): + variable_name = self.__format_variable_name(location, attribute) + variable_value = _format_variable_value(attribute_value) + model[attribute] = _format_as_property(variable_name) + _logger.fine('WLSDPLY-19525', variable_name, attribute_value, attribute, variable_value, + class_name=_class_name, method_name=_method_name) + else: + _logger.finer('WLSDPLY-19526', attribute_value, attribute, str(location), class_name=_class_name, + method_name=_method_name) + if variable_value: + variable_dict[variable_name] = self._check_replace_variable_value(location, attribute, variable_value, + injector_values) + _logger.exiting(class_name=_class_name, method_name=_method_name, result=variable_value) + return variable_dict + + def _process_regexp(self, model, attribute, location, injector_values): + if isinstance(model[attribute], dict): + return self._process_patterns_dictionary(attribute, model[attribute], location, injector_values) + elif type(model[attribute]) == list: + return self._process_patterns_list(attribute, model[attribute], location, injector_values) + else: + return self._process_patterns_string(model, attribute, location, injector_values) + + def _process_patterns_string(self, model, attribute, location, injector_values): + variable_dict = dict() + regexp_list = injector_values[REGEXP] + for dictionary in regexp_list: + pattern = None + suffix = None + if REGEXP_PATTERN in dictionary: + pattern = dictionary[REGEXP_PATTERN] + if REGEXP_SUFFIX in dictionary: + suffix = dictionary[REGEXP_SUFFIX] + variable_name, variable_value = self._process_pattern_string(model, attribute, location, pattern, suffix) + if variable_value: + variable_dict[variable_name] = self._check_replace_variable_value(location, attribute, variable_value, + injector_values) + return variable_dict + + def _process_pattern_string(self, model, attribute, location, pattern, suffix): + _method_name = '_process_regexp_string' + _logger.entering(attribute, location.get_folder_path(), pattern, suffix, class_name=_class_name, + method_name=_method_name) + attribute_value, variable_name, variable_value = self._find_segment_in_string(attribute, model[attribute], + location, pattern, suffix) + if variable_value: + _logger.finer('WLSDPLY-19529', variable_name, attribute_value, attribute, variable_value, + class_name=_class_name, method_name=_method_name) + model[attribute] = attribute_value + # elif replace_if_nosegment: + # check_value = model[attribute] + # if not _already_property(check_value): + # variable_value = check_value + # variable_name = self.__format_variable_name(location, attribute) + # model[attribute] = _format_as_property(variable_name) + # _logger.finer('WLSDPLY-19530', attribute, model[attribute], class_name=_class_name, + # method_name=_method_name) + else: + _logger.finer('WLSDPLY-19524', pattern, attribute, model[attribute], + location.get_folder_path, class_name=_class_name, + method_name=_method_name) + + _logger.exiting(class_name=_class_name, method_name=_method_name, result=variable_value) + return variable_name, variable_value + + def _find_segment_in_string(self, attribute, attribute_value, location, pattern, suffix): + variable_name = None + variable_value = None + if not _already_property(attribute_value): + variable_name = self.__format_variable_name_segment(location, attribute, suffix) + attribute_value, variable_value = _replace_segment(pattern, _format_variable_value(attribute_value), + _format_as_property(variable_name)) + return attribute_value, variable_name, variable_value + + def _process_patterns_list(self, attribute, attribute_value, location, injector_values): + variable_dict = dict() + regexp_list = injector_values[REGEXP] + for dictionary in regexp_list: + pattern = None + suffix = None + if REGEXP_PATTERN in dictionary: + pattern = dictionary[REGEXP_PATTERN] + if REGEXP_SUFFIX in dictionary: + suffix = dictionary[REGEXP_SUFFIX] + variable_name, variable_value = self._process_pattern_list(attribute, attribute_value, location, pattern, + suffix) + if variable_value: + variable_dict[variable_name] = self._check_replace_variable_value(location, attribute, variable_value, + injector_values) + return variable_dict + + def _process_pattern_list(self, attribute_name, attribute_list, location, pattern, suffix): + _method_name = '_process_regexp_list' + _logger.entering(attribute_name, attribute_list, location.get_folder_path(), pattern, suffix, + class_name=_class_name, method_name=_method_name) + variable_name = None + variable_value = None + idx = 0 + for entry in attribute_list: + attribute_value, seg_var_name, seg_var_value = self._find_segment_in_string(attribute_name, entry, location, + pattern, suffix) + if seg_var_value: + _logger.finer('WLSDPLY-19528', variable_name, attribute_name, variable_value, class_name=_class_name, + method_name=_method_name) + attribute_list[idx] = attribute_value + variable_name = seg_var_name + variable_value = seg_var_value + + idx += 1 + # don't break, continue replacing any in dictionary, return the last variable value found + _logger.exiting(class_name=_class_name, method_name=_method_name, result=variable_value) + return variable_name, variable_value + + def _process_patterns_dictionary(self, attribute, attribute_dict, location, injector_values): + variable_dict = dict() + regexp_list = injector_values[REGEXP] + for dictionary in regexp_list: + pattern = None + suffix = None + if REGEXP_PATTERN in dictionary: + pattern = dictionary[REGEXP_PATTERN] + if REGEXP_SUFFIX in dictionary: + suffix = dictionary[REGEXP_SUFFIX] + variable_name, variable_value = self._process_pattern_dictionary(attribute, attribute_dict, location, + pattern, suffix) + if variable_value: + variable_dict[variable_name] = self._check_replace_variable_value(location, attribute, variable_value, + injector_values) + return variable_dict + + def _process_pattern_dictionary(self, attribute_name, attribute_dict, location, regexp, suffix): + _method_name = '_process_regexp_dictionary' + _logger.entering(attribute_name, attribute_dict, location.get_folder_path(), regexp, suffix, + class_name=_class_name, method_name=_method_name) + variable_name = self.__format_variable_name_segment(location, attribute_name, suffix) + variable_value = None + pattern = _compile_pattern(regexp) + if pattern: + replacement = _format_as_property(variable_name) + for entry in attribute_dict: + if not _already_property(attribute_dict[entry]): + matcher = pattern.search(entry) + if matcher: + _logger.finer('WLSDPLY-19527', attribute_name, replacement, class_name=_class_name, + method_name=_method_name) + variable_value = _format_variable_value(attribute_dict[entry]) + attribute_dict[entry] = replacement + # don't break, continue replacing any in dictionary, return the last variable value found + _logger.exiting(class_name=_class_name, method_name=_method_name, result=variable_value) + return variable_name, variable_value + + def _check_name_token(self, location, name_token): + if self.__aliases.requires_unpredictable_single_name_handling(location): + location.add_name_token(name_token, _fake_name_marker) + + def _replace_tokens(self, path_string): + result = path_string + if path_string.startswith(WEBLOGIC_DEPLOY_HOME_TOKEN): + result = path_string.replace(WEBLOGIC_DEPLOY_HOME_TOKEN, _wlsdeploy_location) + elif path_string and self.__model_context: + result = self.__model_context.replace_token_string(path_string) + return result + + def _log_mbean_not_found(self, mbean, replacement, location): + _method_name = '_log_mbean_not_found' + code = ValidationCodes.INVALID + try: + code, __ = self.__aliases.is_valid_model_folder_name(location, mbean) + except AliasException: + pass + if code == ValidationCodes.INVALID: + _logger.warning('WLSDPLY-19515', mbean, replacement, location.get_folder_path(), + class_name=_class_name, method_name=_method_name) + else: + _logger.finer('WLSDPLY-19516', mbean, replacement, location.get_folder_path(), + class_name=_class_name, method_name=_method_name) + + def _get_variable_file_name(self, **kwargs): + _method_name = '_get_variable_file_name' + if VARIABLE_FILE_NAME_ARG in kwargs: + variable_file_location = kwargs[VARIABLE_FILE_NAME_ARG] + _logger.finer('WLSDPLY-19522', variable_file_location, class_name=_class_name, method_name=_method_name) + else: + variable_file_location = variables.get_default_variable_file_name(self.__model_context) + if variable_file_location: + variable_file_location = self._replace_tokens(variable_file_location) + return variable_file_location + + def _write_variables_file(self, variables_dictionary, variables_file_name, append): + _method_name = '_write_variables_file' + _logger.entering(variables_dictionary, variables_file_name, class_name=_class_name, method_name=_method_name) + + written = False + if variables_dictionary: + try: + variables.write_variables(self.__program_name, variables_dictionary, variables_file_name, append) + written = True + except VariableException, ve: + _logger.warning('WLSDPLY-19507', variables_file_name, ve.getLocalizedMessage(), class_name=_class_name, + method_name=_method_name) + _logger.exiting(class_name=_class_name, method_name=_method_name, result=written) + return written + + def _find_special_name(self, mbean): + mbean_name = mbean + mbean_name_list = [] + name_list = _find_special_names_pattern.split(mbean) + if name_list and len(name_list) > 1: + mbean_name = name_list[0] + mbean_name_list = name_list[1].split(',') + if mbean_name_list: + new_list = [] + for entry in mbean_name_list: + if entry in USER_KEYWORD_DICT: + _logger.fine('WLSDPLY-19538', entry, mbean) + try: + method = getattr(variable_injector_functions, USER_KEYWORD_DICT[entry]) + append_list = method(self.__model) + new_list.extend(append_list) + except AttributeError, e: + _logger.warning('WLSDPLY-19539', entry, USER_KEYWORD_DICT[entry], e) + new_list = mbean_name_list + break + else: + new_list.append(entry) + mbean_name_list = new_list + return mbean_name, mbean_name_list + + def _check_insert_attribute_model(self, location, model_section, attribute, injector_values): + _method_name = '_check_insert_attribute_model' + if attribute not in model_section and (FORCE in injector_values and Boolean(injector_values[FORCE])): + value = self.__aliases.get_model_attribute_default_value(location, attribute) + _logger.fine('WLSDPLY-19540', attribute, location.get_folder_path(), value, + class_name=_class_name, method_name=_method_name) + model_section[attribute] = value + + def _check_replace_variable_value(self, location, attribute, variable_value, injector_values): + _method_name = '_format_variable_value' + value = variable_value + if VARIABLE_VALUE in injector_values: + value = injector_values[VARIABLE_VALUE] + # might add code to call a method to populate the replacement value + try: + wlst_attribute_name = self.__aliases.get_wlst_attribute_name(location, attribute) + __, value = self.__aliases.get_model_attribute_name_and_value(location, wlst_attribute_name, value) + _logger.fine('WLSDPLY-19542', value, variable_value, attribute, location.get_folder_path(), + class_name=_class_name, method_name=_method_name) + except AliasException, ae: + _logger.warning('WLSDPLY-19541', value, attribute, location, ae.getLocalizedMessage(), + class_name=_class_name, method_name=_method_name) + return value + + +def get_default_variable_injector_file_name(variable_injector_file_name=VARIABLE_INJECTOR_FILE_NAME): + """ + Return the default name and location of the model variable injector json file + :param variable_injector_file_name: if different than the default name + :return: file path in the wlsdeploy location and file name + """ + return os.path.join(_wlsdeploy_location, DEFAULT_FILE_LOCATION, variable_injector_file_name) + + +def _load_variable_file(variable_file_location, **kwargs): + _method_name = '_load_variable_file' + append = False + variable_dictionary = dict() + if VARIABLE_FILE_APPEND_ARG in kwargs and kwargs[VARIABLE_FILE_APPEND_ARG] in VARIABLE_FILE_APPEND_VALS: + if kwargs[VARIABLE_FILE_APPEND_ARG] == VARIABLE_FILE_APPEND: + _logger.fine('WLSDPLY-19536', variable_file_location, class_name=_class_name, method_name=_method_name) + append = True + elif kwargs[VARIABLE_FILE_APPEND_ARG] == VARIABLE_FILE_UPDATE and os.path.isfile(variable_file_location): + _logger.fine('WLSDPLY-19534', variable_file_location, class_name=_class_name, method_name=_method_name) + try: + variable_dictionary = variables.load_variables(variable_file_location) + except VariableException, ve: + _logger.warning('WLSDPLY-19537', variable_file_location, ve.getLocalizedMessage(), + class_name=_class_name, method_name=_method_name) + else: + _logger.fine('WLSDPLY-19535', variable_file_location, class_name=_class_name, method_name=_method_name) + return append, variable_dictionary + + +def _get_variable_injector_file_name(**kwargs): + variable_injector_file_name = VARIABLE_INJECTOR_FILE_NAME + if VARIABLE_INJECTOR_FILE_NAME_ARG in kwargs: + variable_injector_file_name = kwargs[VARIABLE_INJECTOR_FILE_NAME_ARG] + if VARIABLE_INJECTOR_PATH_NAME_ARG in kwargs: + return os.path.join(kwargs[VARIABLE_INJECTOR_PATH_NAME_ARG], variable_injector_file_name) + else: + return get_default_variable_injector_file_name(variable_injector_file_name) + + +def _get_variable_keywords_file_name(**kwargs): + variable_keywords_file_name = VARIABLE_KEYWORDS_FILE_NAME + if VARIABLE_KEYWORDS_FILE_NAME_ARG in kwargs: + variable_keywords_file_name = kwargs[VARIABLE_KEYWORDS_FILE_NAME_ARG] + if VARIABLE_KEYWORDS_PATH_NAME_ARG in kwargs: + return os.path.join(kwargs[VARIABLE_KEYWORDS_PATH_NAME_ARG], variable_keywords_file_name) + else: + return os.path.join(_wlsdeploy_location, DEFAULT_FILE_LOCATION, variable_keywords_file_name) + + +def _load_variable_injector_file(variable_injector_location): + _method_name = '_load_variable_injector_file' + _logger.entering(variable_injector_location, class_name=_class_name, method_name=_method_name) + variables_dictionary = None + if os.path.isfile(variable_injector_location): + try: + variables_dictionary = JsonToPython(variable_injector_location).parse() + _logger.fine('WLSDPLY-19500', variable_injector_location, class_name=_class_name, method_name=_method_name) + except (IllegalArgumentException, JsonException), e: + _logger.warning('WLSDPLY-19502', variable_injector_location, e.getLocalizedMessage(), + class_name=_class_name, method_name=_method_name) + + _logger.exiting(class_name=_class_name, method_name=_method_name, result=variables_dictionary) + return variables_dictionary + + +def _load_keywords_file(variable_keywords_location): + _method_name = '_load_keywords_file' + _logger.entering(variable_keywords_location, class_name=_class_name, method_name=_method_name) + keywords_dictionary = None + if os.path.isfile(variable_keywords_location): + try: + keywords_dictionary = JsonToPython(variable_keywords_location).parse() + _logger.finer('WLSDPLY-19504', variable_keywords_location, class_name=_class_name, method_name=_method_name) + except (IllegalArgumentException, JsonException), e: + _logger.warning('WLSDPLY-19505', variable_keywords_location, e.getLocalizedMessage(), + class_name=_class_name, method_name=_method_name) + + _logger.exiting(class_name=_class_name, method_name=_method_name, result=keywords_dictionary) + return keywords_dictionary + + +def _create_injector_file_list(variables_dictionary, keyword_dictionary, injector_path): + _method_name = '_create_file_dictionary' + injector_file_list = [] + if CUSTOM_KEYWORD in variables_dictionary: + if KEYWORD_FILES in variables_dictionary[CUSTOM_KEYWORD]: + injector_file_list = variables_dictionary[CUSTOM_KEYWORD][KEYWORD_FILES] + if type(injector_file_list) != list: + injector_file_list = injector_file_list.split(',') + _logger.fine('WLSDPLY-19501', injector_file_list, class_name=_class_name, method_name=_method_name) + else: + _logger.info('WLSDPLY-19512', class_name=_class_name, method_name=_method_name) + del variables_dictionary[CUSTOM_KEYWORD] + for keyword in variables_dictionary: + if keyword in keyword_dictionary: + filename = keyword_dictionary[keyword] + if filename and filename not in injector_file_list: + if not os.path.isabs(filename): + filename = os.path.join(injector_path, filename) + injector_file_list.append(filename) + _logger.finer('WLSDPLY-19508', filename, keyword, class_name=_class_name, method_name=_method_name) + else: + _logger.warning('WLSDPLY-19503', keyword, class_name=_class_name, method_name=_method_name) + return injector_file_list + + +def _get_keyword_files_location(**kwargs): + if VARIABLE_INJECTOR_PATH_NAME_ARG in kwargs: + return kwargs[VARIABLE_INJECTOR_PATH_NAME_ARG] + else: + return os.path.join(_wlsdeploy_location, DEFAULT_FILE_LOCATION, INJECTORS_LOCATION) + + +def _load_injector_file(injector_file_name): + _method_name = '_load_injector_file' + _logger.entering(injector_file_name, class_name=_class_name, method_name=_method_name) + injector_dictionary = dict() + if os.path.isfile(injector_file_name): + try: + injector_dictionary = JsonToPython(injector_file_name).parse() + __temporary_fix(injector_dictionary) + except (IllegalArgumentException, JsonException), e: + _logger.warning('WLDPLY-19409', injector_file_name, e.getLocalizedMessage(), class_name=_class_name, + method_name=_method_name) + else: + _logger.warning('WLSDPLY-19510', injector_file_name, class_name=_class_name, method_name=_method_name) + + _logger.exiting(class_name=_class_name, method_name=_method_name) + return injector_dictionary + + +def _get_append_to_variable_file(**kwargs): + if VARIABLE_FILE_APPEND_ARG in kwargs: + return kwargs[VARIABLE_FILE_APPEND_ARG] + return False + + +def _format_variable_value(value): + if type(value) == bool: + if value: + return 'True' + return 'False' + else: + return str(value) + + +def _massage_name(variable_name): + if variable_name: + variable_name = variable_name.replace('/', '.') + variable_name = _white_space_replacement.sub('-', variable_name) + variable_name = _fake_name_replacement.sub('', variable_name) + return variable_name + + +def _replace_segment(regexp, variable_value, attribute_value): + replaced_value = None + replacement_string = variable_value + pattern = _compile_pattern(regexp) + if pattern: + matcher = pattern.search(variable_value) + if matcher: + temp_value = variable_value[matcher.start():matcher.end()] + if not _already_property(temp_value): + replacement_string = pattern.sub(attribute_value, variable_value) + replaced_value = temp_value + return replacement_string, replaced_value + + +def _compile_pattern(pattern): + try: + return re.compile(pattern) + except Exception, e: + _logger.warning('WLSDPLY-19511', pattern, e, class_name=_class_name, method_name='_compile_pattern') + return None + + +def _already_property(check_string): + return type(check_string) == str and check_string.startswith('@@PROP:') + + +def _format_as_property(prop_name): + return '@@PROP:%s@@' % prop_name + + +def _split_injector(injector_path): + """ + Split the injector path into an mbean list and an attribute name from the injector path string + :param injector_path: + :return: attribute name:mbean list of mbean folder nodes + """ + _method_name = '_split_injector' + attr = None + ml = _split_around_special_names.split(injector_path) + mbean_list = [] + if len(ml) > 0: + attr = ml.pop() + for mbean_item in ml: + if mbean_item: + start = 0 + end = len(mbean_item) + if mbean_item.startswith('\.'): + start += 1 + if mbean_item.endswith('\.'): + end -= 1 + mbean_list.append(mbean_item[start:end]) + _logger.finer('WLSDPLY-19543', mbean_list, attr, class_name=_class_name, method_name=_method_name) + return mbean_list, attr + + +def __temporary_fix(injector_dictionary): + # this is very dangerous - for now, if you want to escape a backslash, need to do 4 backslash. + _method_name = '__temporary_fix' + for value in injector_dictionary.itervalues(): + if REGEXP in value: + for dict_entry in value[REGEXP]: + if REGEXP_PATTERN in dict_entry: + pattern = dict_entry[REGEXP_PATTERN] + listsplit = re.split('\\\\(?!\\\\)', pattern) + if listsplit: + newpattern = '' + for split in listsplit: + newpattern += split[:len(split)] + dict_entry[REGEXP_PATTERN] = newpattern + _logger.fine('Pattern after temporary fix {0}', dict_entry[REGEXP_PATTERN], class_name=_class_name, + method_name=_method_name) diff --git a/core/src/main/python/wlsdeploy/tool/util/variable_injector_functions.py b/core/src/main/python/wlsdeploy/tool/util/variable_injector_functions.py new file mode 100644 index 0000000000..3ceb150e6d --- /dev/null +++ b/core/src/main/python/wlsdeploy/tool/util/variable_injector_functions.py @@ -0,0 +1,51 @@ +""" +Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 +""" +from wlsdeploy.logging.platform_logger import PlatformLogger + +import wlsdeploy.aliases.model_constants as model_constants +import wlsdeploy.util.model as model_sections + +_class_name = 'variable_injector' +_logger = PlatformLogger('wlsdeploy.tool.util') + + +def managed_server_list(model): + """ + Return a managed server name list from the provided model. + :param model: to process for managed server list + :return: list of managed server names or empty list if no managed servers + """ + _method_name = 'managed_server_list' + _logger.entering(class_name=_class_name, method_name=_method_name) + ms_name_list = [] + topology_constant = model_sections.get_model_topology_key() + if topology_constant in model: + topology = model[topology_constant] + if model_constants.SERVER in topology: + ms_name_list = topology[model_constants.SERVER].keys() + if model_constants.ADMIN_SERVER_NAME in topology: + admin_server = topology[model_constants.ADMIN_SERVER_NAME] + if admin_server in ms_name_list: + ms_name_list.remove(admin_server) + _logger.exiting(class_name=_class_name, method_name=_method_name, result=ms_name_list) + return ms_name_list + + +def admin_server_list(model): + """ + Return the domain admin server in list format + :param model: to process for admin server list + :return: admin server in list format + """ + _method_name = 'admin_server_list' + _logger.entering(class_name=_class_name, method_name=_method_name) + as_name_list = [] + topology_constant = model_sections.get_model_topology_key() + if topology_constant in model: + topology = model[topology_constant] + if topology and model_constants.ADMIN_SERVER_NAME in topology: + as_name_list.append(topology[model_constants.ADMIN_SERVER_NAME]) + _logger.exiting(class_name=_class_name, method_name=_method_name, result=as_name_list) + return as_name_list diff --git a/core/src/main/python/wlsdeploy/util/cla_utils.py b/core/src/main/python/wlsdeploy/util/cla_utils.py index ad955f1c37..cb867bed6e 100644 --- a/core/src/main/python/wlsdeploy/util/cla_utils.py +++ b/core/src/main/python/wlsdeploy/util/cla_utils.py @@ -61,6 +61,10 @@ class CommandLineArgUtil(object): ATTRIBUTES_ONLY_SWITCH = '-attributes_only' FOLDERS_ONLY_SWITCH = '-folders_only' RECURSIVE_SWITCH = '-recursive' + # overrides for the variable injector + VARIABLE_INJECTOR_FILE_SWITCH = '-variable_injector_file' + VARIABLE_KEYWORDS_FILE_SWITCH = '-variable_keywords_file' + VARIABLE_PROPERTIES_FILE_SWITCH = '-variable_properties_file' # a slot to stash the parsed domain typedef dictionary DOMAIN_TYPEDEF = 'domain_typedef' # a slot to stash the archive file object @@ -332,6 +336,33 @@ def process_args(self, args): self._add_arg(key, True) elif self.is_recursive_switch(key): self._add_arg(key, True) + elif self.is_variable_injector_file_key(key): + idx += 1 + if idx < args_len: + full_path = self._validate_variable_injector_file_arg(args[idx]) + self._add_arg(key, full_path, True) + else: + ex = self._get_out_of_args_exception(key) + self._logger.throwing(ex, class_name=self._class_name, method_name=method_name) + raise ex + elif self.is_variable_keywords_file_key(key): + idx += 1 + if idx < args_len: + full_path = self._validate_variable_keywords_file_arg(args[idx]) + self._add_arg(key, full_path, True) + else: + ex = self._get_out_of_args_exception(key) + self._logger.throwing(ex, class_name=self._class_name, method_name=method_name) + raise ex + elif self.is_variable_properties_file_key(key): + idx += 1 + if idx < args_len: + full_path = self._validate_variable_properties_file_arg(args[idx]) + self._add_arg(key, full_path, True) + else: + ex = self._get_out_of_args_exception(key) + self._logger.throwing(ex, class_name=self._class_name, method_name=method_name) + raise ex else: ex = exception_helper.create_cla_exception('WLSDPLY-01601', self._program_name, key) ex.setExitCode(self.USAGE_ERROR_EXIT_CODE) @@ -388,7 +419,6 @@ def _validate_oracle_home_arg(self, value): return oh_name - def get_java_home_key(self): return str(self.JAVA_HOME_SWITCH) @@ -507,7 +537,6 @@ def _validate_wlst_path_arg(self, value): return wlst_path.getAbsolutePath() - def get_admin_url_key(self): return self.ADMIN_URL_SWITCH @@ -863,6 +892,61 @@ def _validate_target_mode_arg(self, value): raise ex return + def get_variable_injector_file_key(self): + return self.VARIABLE_INJECTOR_FILE_SWITCH + + def is_variable_injector_file_key(self, key): + return self.VARIABLE_INJECTOR_FILE_SWITCH == key + + def _validate_variable_injector_file_arg(self, value): + method_name = '_validate_variable_injector_file_arg' + + try: + injector = JFileUtils.validateExistingFile(value) + except JIllegalArgumentException, iae: + ex = exception_helper.create_cla_exception('WLSDPLY-01635', value, iae.getLocalizedMessage(), error=iae) + ex.setExitCode(self.ARG_VALIDATION_ERROR_EXIT_CODE) + self._logger.throwing(ex, class_name=self._class_name, method_name=method_name) + raise ex + return injector.getAbsolutePath() + + def get_variable_keywords_file_key(self): + return self.VARIABLE_KEYWORDS_FILE_SWITCH + + def is_variable_keywords_file_key(self, key): + return self.VARIABLE_KEYWORDS_FILE_SWITCH == key + + def _validate_variable_keywords_file_arg(self, value): + method_name = '_validate_variable_keywords_file_arg' + + try: + keywords = JFileUtils.validateExistingFile(value) + except JIllegalArgumentException, iae: + ex = exception_helper.create_cla_exception('WLSDPLY-01636', value, iae.getLocalizedMessage(), error=iae) + ex.setExitCode(self.ARG_VALIDATION_ERROR_EXIT_CODE) + self._logger.throwing(ex, class_name=self._class_name, method_name=method_name) + raise ex + return keywords.getAbsolutePath() + + # use this argument switch for the injector as the variables file does not have to exist + def get_variable_properties_file_key(self): + return self.VARIABLE_PROPERTIES_FILE_SWITCH + + def is_variable_properties_file_key(self, key): + return self.VARIABLE_PROPERTIES_FILE_SWITCH == key + + def _validate_variable_properties_file_arg(self, value): + method_name = '_validate_variable_properties_file_arg' + + try: + variables = JFileUtils.validateFileName(value) + except JIllegalArgumentException, iae: + ex = exception_helper.create_cla_exception('WLSDPLY-01620', value, iae.getLocalizedMessage(), error=iae) + ex.setExitCode(self.ARG_VALIDATION_ERROR_EXIT_CODE) + self._logger.throwing(ex, class_name=self._class_name, method_name=method_name) + raise ex + return variables.getAbsolutePath() + ########################################################################### # Helper methods # ########################################################################### diff --git a/core/src/main/python/wlsdeploy/util/path_utils.py b/core/src/main/python/wlsdeploy/util/path_utils.py index b7675f8239..119fcfdfb5 100644 --- a/core/src/main/python/wlsdeploy/util/path_utils.py +++ b/core/src/main/python/wlsdeploy/util/path_utils.py @@ -105,6 +105,18 @@ def get_filename_from_path(file_path): return file_name +def get_pathname_from_path(file_path): + """ + Return the path without the file name from the existing file path. + :param file_path: file path + :return: path without file name or None if a file name is not present or the file or file path does not exist + """ + file_name = None + if not JStringUtils.isEmpty(file_path) and (os.path.exists(file_path) is False or os.path.isfile(file_path)): + file_path, _ = os.path.split(file_path) + return file_path + + def get_filename_no_ext_from_path(file_path): """ Return the filename with the extension stripped off from the provided file path. diff --git a/core/src/main/python/wlsdeploy/util/variables.py b/core/src/main/python/wlsdeploy/util/variables.py index 9a41a0e2ca..826b6e783d 100644 --- a/core/src/main/python/wlsdeploy/util/variables.py +++ b/core/src/main/python/wlsdeploy/util/variables.py @@ -2,9 +2,12 @@ Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. The Universal Permissive License (UPL), Version 1.0 """ +import os import re +from java.lang import Boolean from java.io import BufferedReader +from java.io import File from java.io import FileInputStream from java.io import FileOutputStream from java.io import FileReader @@ -13,6 +16,7 @@ from oracle.weblogic.deploy.util import PyOrderedDict as OrderedDict +from wlsdeploy.util import path_utils from wlsdeploy.exception import exception_helper from wlsdeploy.logging import platform_logger @@ -54,35 +58,59 @@ def load_variables(file_path): return variable_map -def write_variables(variable_map, file_path): +def write_variables(program_name, variable_map, file_path, append=False): """ Write the dictionary of variables to the specified file. + :param program_name: name of tool that invoked the method which will be written to the variable properties file :param variable_map: the dictionary of variables :param file_path: the file to which to write the properties + :param append: defaults to False. Append properties to the end of file :raises VariableException if an error occurs while storing the variables in the file """ - method_name = 'write_variables' + _method_name = 'write_variables' + _logger.entering(program_name, file_path, append, class_name=_class_name, method_name=_method_name) props = Properties() for key in variable_map: value = variable_map[key] props.setProperty(key, value) - comment = exception_helper.get_message('WLSDPLY-01731') + comment = exception_helper.get_message('WLSDPLY-01731', program_name) output_stream = None try: - output_stream = FileOutputStream(file_path) + output_stream = FileOutputStream(File(file_path), Boolean(append)) props.store(output_stream, comment) output_stream.close() except IOException, ioe: ex = exception_helper.create_variable_exception('WLSDPLY-20007', file_path, ioe.getLocalizedMessage(), error=ioe) - _logger.throwing(ex, class_name=_class_name, method_name=method_name) + _logger.throwing(ex, class_name=_class_name, method_name=_method_name) if output_stream is not None: output_stream.close() raise ex + _logger.exiting(class_name=_class_name, method_name=_method_name) return +def get_default_variable_file_name(model_context): + """ + Generate location and file name for the variable file. + If model file is present, use the model file name and location; + else, use the archive file name and location. + :param model_context: contains the model and archive file arguments + :return: location and file name of variable properties file. + """ + _method_name = 'get_default_variable_file_name' + extract_file_name = model_context.get_model_file() + if not extract_file_name: + extract_file_name = model_context.get_archive_file_name() + default_variable_file = path_utils.get_filename_no_ext_from_path(extract_file_name) + if default_variable_file: + default_variable_file = os.path.join(path_utils.get_pathname_from_path(extract_file_name), + default_variable_file + '.properties') + _logger.finer('WLSDPLY-01736', default_variable_file, class_name=_class_name, method_name=_method_name) + return default_variable_file + + def get_variable_names(text): """ Get the list of variable names in the supplied text. diff --git a/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties b/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties index 8811530ae9..ec7b28f9a7 100644 --- a/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties +++ b/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties @@ -230,6 +230,8 @@ WLSDPLY-01631=Specified target WLST mode {0} is not a valid WLST mode WLSDPLY-01632=Unknown command-line argument {0} for {1}...skipping WLSDPLY-01633=Specified {0} argument {1} does not match the expected pattern: :[/]* WLSDPLY-01634=Specified {0} argument {1} references model section {2} which is not one of the known model sections: {3} +WLSDPLY-01635=Specified Model Variable Injector File {0} is not a valid file : {1} +WLSDPLY-01636=Specified Model Variable Keywords File {0} is not a valid file : {1} # wlsdeploy/util/enum.py WLSDPLY-01700=The value {0} is not a valid value of the Enum type {1} @@ -245,11 +247,12 @@ WLSDPLY-01720=to_boolean() method called with non-boolean value {0} so returning # wlsdeploy/util/variables.py WLSDPLY-01730=Failed to load variables file {0}: {1} -WLSDPLY-01731=Variables updated after encryption +WLSDPLY-01731=Variables updated by {0} WLSDPLY-01732=Variable {0} is not found in properties file WLSDPLY-01733=Variable file {0} cannot be read: {1} WLSDPLY-01734=No value in variable file {0} WLSDPLY-01735=Variable substitution for {0} is deprecated, use @@PROP:{1}@@ +WLSDPLY-01736=Default variable file name {0} # wlsdeploy/util/weblogic_helper.py WLSDPLY-01740=Encryption failed: Unable to locate SerializedSystemIni @@ -418,6 +421,8 @@ WLSDPLY-06018=Please enter the WebLogic administrator password WLSDPLY-06019=Failed to read the WebLogic administrator password input from the user: {0} WLSDPLY-06020=Discover of domain is not currently supported in online mode. Ignoring Admin credential arguments which \ are present for FUTURE TBD release. +WLSDPLY-06021=The variables file command line argument {0} was used but the model variables injector file \ + {1} does not exist : {2} # discoverer.py WLSDPLY-06100=Find attributes at location {0} @@ -1112,6 +1117,66 @@ WLSDPLY-19307=Unable to extract classpath libraries from archive file {0} to dom # wlsdeploy/tool/util/topology_helper.py WLSDPLY-19400=Creating placeholder for server template {0} +# wlsdeploy/tool/util/variable_injector.py +WLSDPLY-19500=Model variable injector values loaded from location {0} +WLSDPLY-19501=Variable replacement using custom file list {0} +WLSDPLY-19502=Unable to read and parse model variables injector json file {0} : {1} +WLSDPLY-19503=Ignoring unknown keyword {0} found in model variable injector file +WLSDPLY-19504=Variable keywords file loaded from location {0} +WLSDPLY-19505=Unable to read and parse variable keywords file {0} : {1} +WLSDPLY-19506=Selecting only the entries from the specified mbean name list {0} for attribute {1} at location {2} +WLSDPLY-19507=Exception attempting to write to variables file {0} - discarding model changes with variable insertions \ + : {1} +WLSDPLY-19508=Adding file {0} to injector file list for keyword {1} +WLSDPLY-19509=Unable to read and load values for property file {0} : {1} +WLSDPLY-19510=Invalid property file name {0} +WLSDPLY-19511=Invalid Regular expression pattern {0} : {1} +WLSDPLY-19512=CUSTOM keyword was found in variables injector list but no files were included. Skipping the CUSTOM \ + keyword +WLSDPLY-19513=Variables were located and inserted in the model using injector file {0} +WLSDPLY-19514=Located mbean {0} in the model file +WLSDPLY-19515=Invalid mbean {0} found in injector directive {1} at location {2} +WLSDPLY-19516=MBean {0} not found in the model for injector directive {1} at location {2} +WLSDPLY-19517=Attribute {0} not found in the model for injector directive {1} at location {2} +WLSDPLY-19518=Variables were inserted into the model and written to the variables file {0} +WLSDPLY-19519=No variables were inserted into the model during variable replacement +WLSDPLY-19520=Variable injector file was found at location {0} but no variable properties file name was provided +WLSDPLY-19522=Variables property file name {0} was passed as an argument to the variable injector +WLSDPLY-19523=MBean {0} from injector path represents a named MBean folder at location {1} +WLSDPLY-19524=Segment {0} for attribute {1} not found in model value {2} at location {3} +WLSDPLY-19525=Variable {0} inserted into the model {1} for attribute {2} and value \ + {3} inserted into variable properties +WLSDPLY-19526=Variable {0} was already inserted into model for attribute {1} at location {2} +WLSDPLY-19527=Segment found in dictionary for attribute {0}; inserting variable replacement {1} into dictionary value +WLSDPLY-19528=Variable {0} was inserted into the model list for attribute {1} and value {2} has been inserted \ + into the variable file +WLSDPLY-19529=Variable {0} was inserted into the model string {1} for attribute {2} and value {3} has been \ + inserted into the variable file +WLSDPLY-19530=Segment was not found in attribute {0} value so entire variable value was replaced by {1} +WLSDPLY-19531=Invalid location {0} for variable injection into attribute {1} : {2} +WLSDPLY-19532=No model variable injector file {0} +WLSDPLY-19533=Will inject variable replacement strings into model using keyword directions found in model \ + variable injector file {0} +WLSDPLY-19534=Update existing variable file {0} with injected variables +WLSDPLY-19535=Create new variable file {0} for injected variables +WLSDPLY-19536=Append existing variable file {0} with injected variables +WLSDPLY-19537=Unable to load variables from existing file {0} and will overwrite the file : {1} +WLSDPLY-19538=Found name keyword {0} for mbean {1} +WLSDPLY-19539=Unable to locate and call mbean name keyword {0} method {1} : {2}. Will inject variables using \ + full mbean name list +WLSDPLY-19540=Attribute {0} not in the model at location {1} but the force attribute is present in the injector \ + keyword so the attribute will be added to the model with the default value {2} +WLSDPLY-19541=Replacement variable value {0} cannot be formatted for the attribute {1} at location {2} : {3} +WLSDPLY-19542=Variable value has been set to {0} and replaces the model value {1} for attribute {2} at location {3} +WLSDPLY-19543=Split injector value into mbean list {0} and attribute {1} + +# wlsdeploy/tool/variable_inject.py +WLSDPLY-19600=Use model variable injector file {0} from command line arguments +WLSDPLY-19601=Use variable injector keywords file {0} from command line arguments +WLSDPLY-19602=Use variable properties file {0} from command line arguments +WLSDPLY-19603=Archive file {0} was provided but does not contain a model file +WLSDPLY-19604=Update model with injected variables + # Common tooling messages used by multiple tools WLSDPLY-20000={0} encountered an unexpected validation error: {1} WLSDPLY-20001={0} did not create the domain because validation failed @@ -1136,3 +1201,5 @@ WLSDPLY-20019=Filter entry in {0} has neither ID or path WLSDPLY-20020=Filter ID {0} is invalid WLSDPLY-20021=Filter path {0} does not exist WLSDPLY-20022=Error loading filter path {0} +WLSDPLY-20023={0} unable to add model file {1} to archive as {2}: {3} +WLSDPLY-20024={0} failed to persist the model to the archive file {1}: {2} diff --git a/core/src/test/python/variable_injector_test.py b/core/src/test/python/variable_injector_test.py new file mode 100644 index 0000000000..2051ba3dfa --- /dev/null +++ b/core/src/test/python/variable_injector_test.py @@ -0,0 +1,324 @@ +""" +Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 +""" +import unittest + +import wlsdeploy.util.variables as variables +import wlsdeploy.tool.util.variable_injector as variable_injector +from wlsdeploy.tool.util.variable_injector import VariableInjector +from wlsdeploy.util.model_translator import FileToPython + + +class VariableFileHelperTest(unittest.TestCase): + _resources_dir = '../../test-classes' + _variable_file = _resources_dir + '/variable.injector.test.properties' + _model_file = _resources_dir + '/variable_insertion.yaml' + _variable_injector_keyword = 'variable_injector_keyword.json' + _keywords_file = 'keywords.json' + + def setUp(self): + self.name = VariableFileHelperTest + self._model = FileToPython(self._model_file).parse() + self._helper = VariableInjector(self.name, self._model, None, '12.2.1.3') + + def testSingleVariableReplacement(self): + replacement_dict = dict() + replacement_dict['Machine.NodeManager.ListenAddress'] = dict() + expected = dict() + expected['Machine.machine1.NodeManager.ListenAddress'] = '127.0.0.1' + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testMultiplesReplacement(self): + expected = dict() + expected['Server.AdminServer.SSL.ListenPort'] = '9002' + expected['Server.AdminServer.ListenPort'] = '9001' + expected['Server.m2.ListenPort'] = '9005' + expected['Server.m1.ListenPort'] = '9003' + expected['Server.m1.SSL.ListenPort'] = '9004' + expected['Server.m2.SSL.ListenPort'] = '9006' + expected['JMSSystemResource.MyJmsModule.JmsResource.ForeignServer.MyForeignServer.ConnectionURL'] \ + = 't3://my.other.cluster:7001' + expected['JMSSystemResource.MyJmsModule.JmsResource.ForeignServer.MyForeignServer.' + 'ForeignDestination.MyRemoteQ.LocalJNDIName'] = 'jms/remoteQ' + replacement_dict = dict() + replacement_dict['Server.ListenPort'] = dict() + replacement_dict['JMSSystemResource.JmsResource.ForeignServer.ConnectionURL'] = dict() + replacement_dict['JMSSystemResource.JmsResource.ForeignServer.ForeignDestination.LocalJNDIName'] = dict() + replacement_dict['Server.SSL.ListenPort'] = dict() + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testInvalidMBeanNameNoException(self): + expected = dict() + replacement_dict = dict() + replacement_dict['JmsSystemResource.Notes'] = dict() + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testInvalidAttributeName(self): + expected = dict() + replacement_dict = dict() + replacement_dict['Server.listenaddress'] = dict() + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testDomainAttributeReplacementAndModel(self): + expected = dict() + expected['Notes'] = 'Test note replacement' + expected_replacement = '@@PROP:Notes@@' + replacement_dict = dict() + replacement_dict['Notes'] = dict() + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + self.assertEqual(expected_replacement, self._model['topology']['Notes']) + + def testWithSegment(self): + expected = dict() + expected['JDBCSystemResource.Database2.JdbcResource.JDBCDriverParams.URL--Host'] = \ + 'slc05til.us.oracle.com' + expected['JDBCSystemResource.Database2.JdbcResource.JDBCDriverParams.URL--Port'] = \ + '1521' + replacement_dict = dict() + replacement_dict['JDBCSystemResource.JdbcResource.JDBCDriverParams.URL'] = dict() + list_entry1 = dict() + list_entry1[variable_injector.REGEXP_PATTERN] = '(?<=PORT=)[\w.-]+(?=\))' + list_entry1[variable_injector.REGEXP_SUFFIX] = 'Port' + list_entry2 = dict() + list_entry2[variable_injector.REGEXP_PATTERN] = '(?<=HOST=)[\w.-]+(?=\))' + list_entry2[variable_injector.REGEXP_SUFFIX] = 'Host' + replacement_dict['JDBCSystemResource.JdbcResource.JDBCDriverParams.URL'][variable_injector.REGEXP] = [ + list_entry1, list_entry2] + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + db2 = 'jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' \ + '(HOST=@@PROP:JDBCSystemResource.Database2.JdbcResource.JDBCDriverParams.URL--Host@@)' \ + '(PORT=@@PROP:JDBCSystemResource.Database2.JdbcResource.JDBCDriverParams.URL--Port@@)))' \ + '(CONNECT_DATA=(SERVICE_NAME=orcl.us.oracle.com)))' + db1 = 'jdbc:oracle:thin:@//den00chv.us.oracle.com:1521/PDBORCL' + self.assertEqual(db2, self._model['resources']['JDBCSystemResource']['Database2']['JdbcResource'][ + 'JDBCDriverParams']['URL']) + self.assertEqual(db1, self._model['resources']['JDBCSystemResource']['Database1']['JdbcResource'][ + 'JDBCDriverParams']['URL']) + + def testWithSegmentInDictionary(self): + expected = dict() + expected['MailSession.MailSession-0.Properties--SmtpHost'] = 'stbeehive.oracle.com' + expected['MailSession.MyMailSession.Properties--SmtpHost'] = 'stbeehive.oracle.com' + expected['MailSession.MailSession-0.Properties--ImapHost'] = 'stbeehive.oracle.com' + expected['MailSession.MyMailSession.Properties--ImapHost'] = 'stbeehive.oracle.com' + replacement_dict = dict() + replacement_dict['MailSession.Properties'] = dict() + list_entry1 = dict() + list_entry1[variable_injector.REGEXP_PATTERN] = 'mail.smtp.host' + list_entry1[variable_injector.REGEXP_SUFFIX] = 'SmtpHost' + list_entry2 = dict() + list_entry2[variable_injector.REGEXP_PATTERN] = 'mail.imap.host' + list_entry2[variable_injector.REGEXP_SUFFIX] = 'ImapHost' + replacement_dict['MailSession.Properties'][variable_injector.REGEXP] = [list_entry1, list_entry2] + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + self.assertEqual('@@PROP:MailSession.MyMailSession.Properties--SmtpHost@@', + self._model['resources']['MailSession']['MyMailSession']['Properties']['mail.smtp.host']) + self.assertEqual('@@PROP:MailSession.MyMailSession.Properties--ImapHost@@', + self._model['resources']['MailSession']['MyMailSession']['Properties']['mail.imap.host']) + + def testWithSegmentInDictionaryAndAPattern(self): + expected = dict() + expected['MailSession.MyMailSession.Properties--Host'] = 'stbeehive.oracle.com' + expected['MailSession.MailSession-0.Properties--Host'] = 'stbeehive.oracle.com' + replacement_dict = dict() + replacement_dict['MailSession.Properties'] = dict() + list_entry = dict() + list_entry[variable_injector.REGEXP_PATTERN] = '(?<=\w.)host' + list_entry[variable_injector.REGEXP_SUFFIX] = 'Host' + replacement_dict['MailSession.Properties'][variable_injector.REGEXP] = [list_entry] + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + self.assertEqual('@@PROP:MailSession.MyMailSession.Properties--Host@@', + self._model['resources']['MailSession']['MyMailSession']['Properties']['mail.imap.host']) + self.assertEqual('@@PROP:MailSession.MyMailSession.Properties--Host@@', + self._model['resources']['MailSession']['MyMailSession']['Properties']['mail.host']) + self.assertEqual('@@PROP:MailSession.MyMailSession.Properties--Host@@', + self._model['resources']['MailSession']['MyMailSession']['Properties']['mail.smtp.host']) + + def testWithSegmentInList(self): + expected = dict() + expected['WLDFSystemResource.MyWldfModule.WLDFResource.Harvester.HarvestedType.weblogic.management.' + 'runtime.ServerRuntimeMBean.HarvestedAttribute'] = 'OracleHome' + replacement_dict = dict() + replacement_dict['WLDFSystemResource.WLDFResource.Harvester.HarvestedType.HarvestedAttribute'] = dict() + list_entry = dict() + list_entry[variable_injector.REGEXP_PATTERN] = 'OracleHome' + replacement_dict['WLDFSystemResource.WLDFResource.Harvester.HarvestedType.HarvestedAttribute'][ + variable_injector.REGEXP] = [list_entry] + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + wldf_list = self._model['resources']['WLDFSystemResource']['MyWldfModule']['WLDFResource']['Harvester'][ + 'HarvestedType']['weblogic.management.runtime.ServerRuntimeMBean']['HarvestedAttribute'] + found = False + for entry in wldf_list: + if entry == '@@PROP:WLDFSystemResource.MyWldfModule.WLDFResource.Harvester.HarvestedType.' \ + 'weblogic.management.runtime.ServerRuntimeMBean.HarvestedAttribute@@': + found = True + break + self.assertEqual(True, found) + + def testWithSegmentInStringInList(self): + expected = dict() + expected['WLDFSystemResource.MyWldfModule.WLDFResource.Harvester.HarvestedType.weblogic.management.' + 'runtime.ServerRuntimeMBean.HarvestedInstance--ManagedServer'] = 'm1' + replacement_dict = dict() + replacement_dict['WLDFSystemResource.WLDFResource.Harvester.HarvestedType.HarvestedInstance'] = dict() + list_entry = dict() + list_entry[variable_injector.REGEXP_PATTERN] = 'm1' + list_entry[variable_injector.REGEXP_SUFFIX] = 'ManagedServer' + replacement_dict['WLDFSystemResource.WLDFResource.Harvester.HarvestedType.HarvestedInstance'][ + variable_injector.REGEXP] = [list_entry] + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + wldf_list = self._model['resources']['WLDFSystemResource']['MyWldfModule']['WLDFResource']['Harvester'][ + 'HarvestedType']['weblogic.management.runtime.ServerRuntimeMBean']['HarvestedInstance'] + found = False + for entry in wldf_list: + if entry == 'com.bea:Name=@@PROP:WLDFSystemResource.MyWldfModule.WLDFResource.Harvester.HarvestedType.' \ + 'weblogic.management.runtime.ServerRuntimeMBean.HarvestedInstance--ManagedServer@@' \ + ',Type=ServerRuntime': + found = True + break + self.assertEqual(True, found) + + def testWithMBeanName(self): + expected = dict() + expected['JDBCSystemResource.Database2.JdbcResource.JDBCDriverParams.Properties.user.Value'] = 'sys as dba' + expected['JDBCSystemResource.Database1.JdbcResource.JDBCDriverParams.Properties.user.Value'] = 'admin' + replacement_dict = dict() + replacement_dict['JDBCSystemResource.JdbcResource.JDBCDriverParams.Properties[user].Value'] = dict() + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testWithListMBeanName(self): + expected = dict() + expected['Server.m1.SSL.Enabled'] = 'True' + expected['Server.m2.SSL.Enabled'] = 'True' + replacement_dict = dict() + replacement_dict['Server[m1,m2].SSL.Enabled'] = dict() + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testWithManagedServerKeyword(self): + expected = dict() + expected['Server.m1.SSL.Enabled'] = 'True' + expected['Server.m2.SSL.Enabled'] = 'True' + replacement_dict = dict() + replacement_dict['Server[MANAGED_SERVERS].SSL.Enabled'] = dict() + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testWithMultiKeyword(self): + expected = dict() + expected['Server.AdminServer.SSL.Enabled'] = 'True' + expected['Server.m1.SSL.Enabled'] = 'True' + expected['Server.m2.SSL.Enabled'] = 'True' + replacement_dict = dict() + replacement_dict['Server[MANAGED_SERVERS,ADMIN_SERVER].SSL.Enabled'] = dict() + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testWithVariableHelperKeywords(self): + expected = dict() + expected['JMSSystemResource.MyJmsModule.JmsResource.ForeignServer.MyForeignServer.ConnectionURL'] \ + = 't3://my.other.cluster:7001' + expected['Server.AdminServer.ListenPort'] = '9001' + expected['Server.m2.ListenPort'] = '9005' + expected['Server.m1.ListenPort'] = '9003' + expected['Machine.machine1.NodeManager.ListenPort'] = '5557' + expected['Machine.machine1.NodeManager.PasswordEncrypted'] = '--FIX ME--' + expected['Machine.machine1.NodeManager.UserName'] = 'admin' + inserted, model, variable_file_name = self._helper.inject_variables_keyword_file( + variable_file_name=self._variable_file, + variable_injector_path_name=self._resources_dir, + variable_injector_file_name=self._variable_injector_keyword, + variable_keywords_path_name=self._resources_dir, variable_keywords_file_name=self._keywords_file) + self.assertEqual(self._variable_file, variable_file_name) + self.assertEqual(True, inserted) + actual = variables.load_variables(self._variable_file) + self._compare_to_expected_dictionary(expected, actual) + + def testForceAttribute(self): + expected = dict() + expected['Server.AdminServer.SSL.HostnameVerificationIgnored'] = 'false' + expected['Server.m1.SSL.HostnameVerificationIgnored'] = 'false' + expected['Server.m2.SSL.HostnameVerificationIgnored'] = 'false' + replacement_dict = dict() + replacement_dict['Server.SSL.HostnameVerificationIgnored'] = dict() + replacement_dict['Server.SSL.HostnameVerificationIgnored'][variable_injector.FORCE] = True + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testForceAttributeWithTwoDefaults(self): + expected = dict() + expected['JMSSystemResource.MyJmsModule.JmsResource.Template.JmsTemplate.MaximumMessageSize'] = '0' + replacement_dict = dict() + replacement_dict['JMSSystemResource.JmsResource.Template.MaximumMessageSize'] = dict() + replacement_dict['JMSSystemResource.JmsResource.Template.MaximumMessageSize'][variable_injector.FORCE] = True + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testReplaceVariableValueAttribute(self): + expected = dict() + expected[ + 'JMSSystemResource.MyJmsModule.JmsResource.ForeignServer.MyForeignServer.JNDIProperty' + '.java.naming.security.principal.Value'] = 'k8s' + replacement_dict = dict() + replacement_dict['JMSSystemResource.JmsResource.ForeignServer.' + 'JNDIProperty[java.naming.security.principal].Value'] = dict() + replacement_dict['JMSSystemResource.JmsResource.ForeignServer.' + 'JNDIProperty[java.naming.security.principal].Value'][ + variable_injector.VARIABLE_VALUE] = 'k8s' + actual = self._helper.inject_variables(replacement_dict) + print actual + self._compare_to_expected_dictionary(expected, actual) + + def testReplaceVariableValueSegmentInString(self): + expected = dict() + expected['JDBCSystemResource.Database2.JdbcResource.JDBCDriverParams.URL--Host'] = \ + 'den00chv' + replacement_dict = dict() + replacement_dict['JDBCSystemResource[Database2].JdbcResource.JDBCDriverParams.URL'] = dict() + list_entry = dict() + list_entry[variable_injector.REGEXP_PATTERN] = '(?<=HOST=)[\w.-]+(?=\))' + list_entry[variable_injector.REGEXP_SUFFIX] = 'Host' + replacement_dict['JDBCSystemResource[Database2].JdbcResource.JDBCDriverParams.URL'][ + variable_injector.REGEXP] = [list_entry] + replacement_dict['JDBCSystemResource[Database2].JdbcResource.JDBCDriverParams.URL'][ + variable_injector.VARIABLE_VALUE] = 'den00chv' + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def testReplaceVariableValueSegmentInDictionary(self): + expected = dict() + expected['MailSession.MailSession-0.Properties--SmtpHost'] = 'localhost' + expected['MailSession.MyMailSession.Properties--SmtpHost'] = 'localhost' + replacement_dict = dict() + replacement_dict['MailSession.Properties'] = dict() + list_entry = dict() + list_entry[variable_injector.REGEXP_PATTERN] = 'mail.smtp.host' + list_entry[variable_injector.REGEXP_SUFFIX] = 'SmtpHost' + replacement_dict['MailSession.Properties'][variable_injector.REGEXP] = [list_entry] + replacement_dict['MailSession.Properties'][variable_injector.VARIABLE_VALUE] = 'localhost' + actual = self._helper.inject_variables(replacement_dict) + self._compare_to_expected_dictionary(expected, actual) + + def _compare_to_expected_dictionary(self, expected, actual): + self.assertEqual(len(expected), len(actual), + 'Not the same number of entries : expected=' + str(len(expected)) + ', actual=' + str( + len(actual))) + for k, v in actual.iteritems(): + self.assertEqual(True, k in expected and v == expected[k], 'Actual item not in expected ' + k + + ' : ' + v + ' expected=' + str(expected)) + + +if __name__ == '__main__': + unittest.main() diff --git a/core/src/test/resources/credentials.json b/core/src/test/resources/credentials.json new file mode 100644 index 0000000000..e777cc2bef --- /dev/null +++ b/core/src/test/resources/credentials.json @@ -0,0 +1,4 @@ +{ + "Machine.NodeManager.PasswordEncrypted": {}, + "Machine.NodeManager.UserName": {} +} diff --git a/core/src/test/resources/custom.json b/core/src/test/resources/custom.json new file mode 100644 index 0000000000..493b0fba8c --- /dev/null +++ b/core/src/test/resources/custom.json @@ -0,0 +1,4 @@ +{ + "Notes": {}, + "Application.SecurityDDModel": {} +} diff --git a/core/src/test/resources/keywords.json b/core/src/test/resources/keywords.json new file mode 100644 index 0000000000..75de751503 --- /dev/null +++ b/core/src/test/resources/keywords.json @@ -0,0 +1,6 @@ +{ + "PORT": "port.json", + "HOST": "host.json", + "URL": "url.json", + "CREDENTIALS": "credentials.json" +} diff --git a/core/src/test/resources/port.json b/core/src/test/resources/port.json new file mode 100644 index 0000000000..c5b6d0355f --- /dev/null +++ b/core/src/test/resources/port.json @@ -0,0 +1,4 @@ +{ + "Server.ListenPort": {}, + "Machine.NodeManager.ListenPort": {} +} diff --git a/core/src/test/resources/url.json b/core/src/test/resources/url.json new file mode 100644 index 0000000000..9159c1ace3 --- /dev/null +++ b/core/src/test/resources/url.json @@ -0,0 +1,3 @@ +{ + "JMSSystemResource.JmsResource.ForeignServer.ConnectionURL": {} +} diff --git a/core/src/test/resources/variable_injector_keyword.json b/core/src/test/resources/variable_injector_keyword.json new file mode 100644 index 0000000000..2b8da6ac04 --- /dev/null +++ b/core/src/test/resources/variable_injector_keyword.json @@ -0,0 +1,5 @@ +{ + "PORT": {}, + "URL": {}, + "CREDENTIALS": {} +} diff --git a/core/src/test/resources/variable_insertion.yaml b/core/src/test/resources/variable_insertion.yaml new file mode 100644 index 0000000000..6fe7e99aca --- /dev/null +++ b/core/src/test/resources/variable_insertion.yaml @@ -0,0 +1,158 @@ +domainInfo: + ServerStartMode: prod + AdminUserName: weblogic + AdminPassword: '--FIX-ME--' +topology: + Name: DemoDomain + AdminServerName: AdminServer + DomainVersion: 12.2.1.3.0 + Notes: 'Test note replacement' + Machine: + machine1: + NodeManager: + ListenAddress: 127.0.0.1 + ListenPort: 5557 + Notes: The only node manager + PasswordEncrypted: '--FIX ME--' + UserName: 'admin' + Notes: The only machine + Server: + m2: + ListenAddress: 127.0.0.1 + Machine: machine1 + Cluster: mycluster + SSL: + Enabled: true + ListenPort: 9006 + ServerStart: + Arguments: '-Doracle.net.tns_admin=/etc -DANTLR_USE_DIRECT_CLASS_LOADING=true -DANTLR_USE_DIRECT_CLASS_LOADING=true -Djava.awt.headless=true -Dhttp.webdir.enable=false -Duser.timezone=Europe/Zurich -Djava.net.preferIPv4Stack=true -Djava.security.egd=file:/dev/./urandom -Dweblogic.data.canTransferAnyFile=true' + ClassPath: 'wlsdeploy/classpathLibraries/WlsAttributeNameMapper-2.0.jar' + ListenPort: 9005 + m1: + ListenAddress: 127.0.0.1 + Machine: machine1 + Cluster: mycluster + SSL: + Enabled: true + ListenPort: 9004 + DefaultFileStore: + InitialSize: 512 + ListenPort: 9003 + AdminServer: + ListenAddress: 127.0.0.1 + Machine: machine1 + SSL: + Enabled: true + ListenPort: 9002 + ListenPort: 9001 +resources: + SelfTuning: + MaxThreadsConstraint: + ThreeMax: + Count: 3 + WorkManager: + MaxThWM: + Target: mycluster + MailSession: + MyMailSession: + Properties: + mail.host: stbeehive.oracle.com + mail.store.protocol: imap + mail.imap.port: 993L + mail.smtp.ssl.enable: True + mail.imap.auth: True + mail.transport.protocol: smtp + mail.imap.ssl.enable: True + mail.smtp.host: stbeehive.oracle.com + mail.smtp.starttls.enable: True + mail.smtp.port: 465L + mail.smtp.auth: True + mail.imap.host: stbeehive.oracle.com + mail.imap.starttls.enable: True + SessionUsername: 'john.smith@oracle.com' + JNDIName: mail/MyMailSession + Target: mycluster + SessionPasswordEncrypted: '--FIX ME--' + 'MailSession-0': + Properties: + mail.imap.port: 996L + mail.smtp.port: 465L + mail.imap.host: stbeehive.oracle.com + mail.smtp.host: stbeehive.oracle.com + mail.store.protocol: imap + SessionUsername: weblogic + JNDIName: javamail/oracle + Target: mycluster + SessionPasswordEncrypted: '--FIX ME--' + JMSSystemResource: + MyJmsModule: + JmsResource: + ForeignServer: + MyForeignServer: + ForeignDestination: + MyRemoteQ: + RemoteJndiName: jms/myQ + LocalJNDIName: jms/remoteQ + ForeignConnectionFactory: + MyRemoteCF: + RemoteJndiName: jms/myCF + LocalJNDIName: jms/remoteCF + ConnectionURL: 't3://my.other.cluster:7001' + JNDIProperty: + java.naming.security.principal: + Key: java.naming.security.principal + Value: weblogic + bar: + Key: bar + Value: True + JNDIPropertiesCredentialEncrypted: '--FIX ME--' + Template: + JmsTemplate: + InsertionPausedAtStartup: true + JDBCSystemResource: + Database1: + DescriptorFileName: 'jdbc/Database1-3195-jdbc.xml' + Target: mycluster + JdbcResource: + JDBCDriverParams: + Properties: + oracle.jdbc.ReadTimeout: + Value: 30000 + user: + Value: admin + oracle.net.CONNECT_TIMEOUT: + Value: 5000 + URL: 'jdbc:oracle:thin:@//den00chv.us.oracle.com:1521/PDBORCL' + PasswordEncrypted: '--FIX ME--' + DriverName: oracle.jdbc.xa.client.OracleXADataSource + Database2: + DescriptorFileName: 'jdbc/Database2-3194-jdbc.xml' + Target: mycluster + JdbcResource: + JDBCDriverParams: + Properties: + oracle.jdbc.ReadTimeout: + Value: 30000 + user: + Value: sys as dba + oracle.net.CONNECT_TIMEOUT: + Value: 5000 + URL: 'jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=slc05til.us.oracle.com)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl.us.oracle.com)))' + PasswordEncrypted: '--FIX ME--' + DriverName: oracle.jdbc.xa.client.OracleXADataSource + WLDFSystemResource: + MyWldfModule: + WLDFResource: + Target: mycluster + Harvester: + SamplePeriod: 6000000 + HarvestedType: + weblogic.management.runtime.ServerRuntimeMBean: + Enabled: true + Namespace: ServerRuntime + HarvestedInstance: [ 'com.bea:Name=AdminServer,Type=ServerRuntime', 'com.bea:Name=m1,Type=ServerRuntime' ] + HarvestedAttribute: [ CurrentDirectory, MiddlewareHome, OracleHome, ServerClasspath, ServerStartupTime ] + weblogic.management.runtime.PersistentStoreRuntimeMBean: + Namespace: DomainRuntime + HarvestedInstance: [ ] + HarvestedAttribute: [ AllocatedIoBufferBytes ] diff --git a/installer/src/assembly/zip.xml b/installer/src/assembly/zip.xml index f101dcf350..acda1db1f8 100644 --- a/installer/src/assembly/zip.xml +++ b/installer/src/assembly/zip.xml @@ -54,6 +54,20 @@ unix + + src/main/lib + lib + 0750 + unix + + + + src/main/samples + samples + 0750 + unix + + .. . diff --git a/installer/src/main/bin/discoverDomain.cmd b/installer/src/main/bin/discoverDomain.cmd index 46a56727d2..f163d81570 100644 --- a/installer/src/main/bin/discoverDomain.cmd +++ b/installer/src/main/bin/discoverDomain.cmd @@ -115,6 +115,13 @@ IF %JVM_VERSION% LSS 7 ( ECHO JDK version is %JVM_FULL_VERSION%, setting JAVA_VENDOR to Sun... SET JAVA_VENDOR=Sun ) +@rem +@rem Check to see if no args were given and print the usage message +@rem +IF "%~1" == "" ( + SET RETURN_CODE=0 + GOTO usage +) @rem @rem Find the args required to determine the WLST script to run @@ -125,6 +132,10 @@ SET DOMAIN_TYPE= SET WLST_PATH_DIR= :arg_loop +IF "%1" == "-help" ( + SET RETURN_CODE=0 + GOTO usage +) IF "%1" == "-oracle_home" ( SET ORACLE_HOME=%2 SHIFT @@ -295,8 +306,6 @@ ECHO. ECHO discoverDomain.cmd failed ^(exit code = %RETURN_CODE%^) >&2 GOTO exit_script -:usage -ECHO. :usage ECHO. ECHO Usage: %~nx0 -oracle_home ^ diff --git a/installer/src/main/bin/injectVariables.cmd b/installer/src/main/bin/injectVariables.cmd new file mode 100644 index 0000000000..33b1fb7aa3 --- /dev/null +++ b/installer/src/main/bin/injectVariables.cmd @@ -0,0 +1,358 @@ +@ECHO OFF +@rem ************************************************************************** +@rem injectVariables.cmd +@rem +@rem Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +@rem The Universal Permissive License (UPL), Version 1.0 +@rem +@rem NAME +@rem injectVariables.cmd - Inject variables into the model. +@rem +@rem DESCRIPTION +@rem This script will inject variable tokens into the model and persist the variables to the +@rem indicated variable file. This can be run against a model that has injected variables. Any +@rem injected variables will not be replaced. If the existing variable file was provided, the +@rem new injected variables will be appended to the file. +@rem +@rem +@rem +@rem This script uses the following command-line arguments directly, the rest +@rem of the arguments are passed down to the underlying python program: +@rem +@rem - -oracle_home The directory of the existing Oracle Home to use. +@rem This directory must exist and it is the caller^'s +@rem responsibility to verify that it does. This +@rem argument is required. +@rem +@rem - -domain_type The type of domain to create. This argument is +@rem is optional. If not specified, it defaults to WLS. +@rem +@rem - -wlst_path The path to the Oracle Home product directory under +@rem which to find the wlst.cmd script. This is only +@rem needed for pre-12.2.1 upper stack products like SOA. +@rem +@rem For example, for SOA 12.1.3, -wlst_path should be +@rem specified as %ORACLE_HOME%\soa +@rem +@rem This script uses the following variables: +@rem +@rem JAVA_HOME - The location of the JDK to use. The caller must set +@rem this variable to a valid Java 7 (or later) JDK. +@rem +@rem WLSDEPLOY_HOME - The location of the WLS Deploy installation. +@rem If the caller sets this, the callers location will be +@rem honored provided it is an existing directory. +@rem Otherwise, the location will be calculated from the +@rem location of this script. +@rem +@rem WLSDEPLOY_PROPERTIES - Extra system properties to pass to WLST. The caller +@rem can use this environment variable to add additional +@rem system properties to the WLST environment. +@rem + +SETLOCAL + +SET WLSDEPLOY_PROGRAM_NAME=injectVariables + +SET SCRIPT_PATH=%~dp0 +FOR %%i IN ("%SCRIPT_PATH%") DO SET SCRIPT_PATH=%%~fsi +IF %SCRIPT_PATH:~-1%==\ SET SCRIPT_PATH=%SCRIPT_PATH:~0,-1% + +IF NOT DEFINED WLSDEPLOY_HOME ( + SET WLSDEPLOY_HOME=%SCRIPT_PATH%\.. +) ELSE ( + IF NOT EXIST "%WLSDEPLOY_HOME%" ( + ECHO Specified WLSDEPLOY_HOME of "%WLSDEPLOY_HOME%" does not exist >&2 + SET RETURN_CODE=2 + GOTO exit_script + ) +) +FOR %%i IN ("%WLSDEPLOY_HOME%") DO SET WLSDEPLOY_HOME=%%~fsi +IF %WLSDEPLOY_HOME:~-1%==\ SET WLSDEPLOY_HOME=%WLSDEPLOY_HOME:~0,-1% + +@rem +@rem Make sure that the JAVA_HOME environment variable is set to point to a +@rem JDK 7 or higher JVM (and that it isn't OpenJDK). +@rem +IF NOT DEFINED JAVA_HOME ( + ECHO Please set the JAVA_HOME environment variable to point to a Java 7 installation >&2 + SET RETURN_CODE=2 + GOTO exit_script +) ELSE ( + IF NOT EXIST "%JAVA_HOME%" ( + ECHO Your JAVA_HOME environment variable to points to a non-existent directory: %JAVA_HOME% >&2 + SET RETURN_CODE=2 + GOTO exit_script + ) +) +FOR %%i IN ("%JAVA_HOME%") DO SET JAVA_HOME=%%~fsi +IF %JAVA_HOME:~-1%==\ SET JAVA_HOME=%JAVA_HOME:~0,-1% + +IF EXIST %JAVA_HOME%\bin\java.exe ( + FOR %%i IN ("%JAVA_HOME%\bin\java.exe") DO SET JAVA_EXE=%%~fsi +) ELSE ( + ECHO Java executable does not exist at %JAVA_HOME%\bin\java.exe does not exist >&2 + SET RETURN_CODE=2 + GOTO exit_script +) + +FOR /F %%i IN ('%JAVA_EXE% -version 2^>^&1') DO ( + IF "%%i" == "OpenJDK" ( + ECHO JAVA_HOME %JAVA_HOME% contains OpenJDK^, which is not supported >&2 + SET RETURN_CODE=2 + GOTO exit_script + ) +) + +FOR /F tokens^=2-5^ delims^=.-_^" %%j IN ('%JAVA_EXE% -fullversion 2^>^&1') DO ( + SET "JVM_FULL_VERSION=%%j.%%k.%%l_%%m" + SET "JVM_VERSION=%%k" +) + +IF %JVM_VERSION% LSS 7 ( + ECHO You are using an unsupported JDK version %JVM_FULL_VERSION% >&2 + SET RETURN_CODE=2 + GOTO exit_script +) ELSE ( + ECHO JDK version is %JVM_FULL_VERSION%, setting JAVA_VENDOR to Sun... + SET JAVA_VENDOR=Sun +) + +@rem +@rem Check to see if no args were given and print the usage message +@rem +IF "%~1" == "" ( + SET RETURN_CODE=0 + GOTO usage +) + +@rem +@rem Find the args required to determine the WLST script to run +@rem + +SET ORACLE_HOME= +SET DOMAIN_TYPE= +SET WLST_PATH_DIR= + +:arg_loop +IF "%1" == "-help" ( + SET RETURN_CODE=0 + GOTO usage +) +IF "%1" == "-oracle_home" ( + SET ORACLE_HOME=%2 + SHIFT + GOTO arg_continue +) +IF "%1" == "-domain_type" ( + SET DOMAIN_TYPE=%2 + SHIFT + GOTO arg_continue +) +IF "%1" == "-wlst_path" ( + SET WLST_PATH_DIR=%2 + SHIFT + GOTO arg_continue +) +@REM If none of the above, unknown argument so skip it +:arg_continue +SHIFT +IF NOT "%~1" == "" ( + GOTO arg_loop +) + +@rem +@rem Check for values of required arguments for this script to continue. +@rem The underlying WLST script has other required arguments. +@rem +IF "%ORACLE_HOME%" == "" ( + ECHO Required argument ORACLE_HOME not provided >&2 + SET RETURN_CODE=99 + GOTO usage +) + +@rem +@rem If the WLST_PATH_DIR is specified, validate that it contains the wlst.cmd script +@rem +IF DEFINED WLST_PATH_DIR ( + FOR %%i IN ("%WLST_PATH_DIR%") DO SET WLST_PATH_DIR=%%~fsi + IF NOT EXIST "%WLST_PATH_DIR%" ( + ECHO WLST_PATH_DIR specified does not exist: %WLST_PATH_DIR% >&2 + SET RETURN_CODE=98 + GOTO exit_script + ) + set "WLST=%WLST_PATH_DIR%\common\bin\wlst.cmd" + IF NOT EXIST "%WLST%" ( + ECHO WLST executable %WLST% not found under specified WLST_PATH_DIR %WLST_PATH_DIR% >&2 + SET RETURN_CODE=98 + GOTO exit_script + ) + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + SET WLST_EXT_CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + GOTO found_wlst +) + +@rem +@rem Find the location for wlst.cmd +@rem +SET WLST= +SET USE_JRF_WLST=FALSE +IF DEFINED DOMAIN_TYPE ( + IF "%DOMAIN_TYPE%" == "WLS" ( + SET USE_JRF_WLST=FALSE + GOTO domain_type_recognized + ) + IF "%DOMAIN_TYPE%" == "RestrictedJRF" ( + SET USE_JRF_WLST=TRUE + GOTO domain_type_recognized + ) + IF "%DOMAIN_TYPE%" == "JRF" ( + SET USE_JRF_WLST=TRUE + GOTO domain_type_recognized + ) + ECHO Domain type %DOMAIN_TYPE% not recognized by shell script...assuming JRF is required + SET USE_JRF_WLST=TRUE +) + +:domain_type_recognized +IF "%USE_JRF_WLST%" == "TRUE" ( + IF EXIST "%ORACLE_HOME%\oracle_common\common\bin\wlst.cmd" ( + SET WLST=%ORACLE_HOME%\oracle_common\common\bin\wlst.cmd + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + SET WLST_EXT_CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + GOTO found_wlst + ) +) ELSE ( + IF EXIST "%ORACLE_HOME%\wlserver_10.3\common\bin\wlst.cmd" ( + SET WLST=%ORACLE_HOME%\wlserver_10.3\common\bin\wlst.cmd + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + GOTO found_wlst + ) + IF EXIST "%ORACLE_HOME%\wlserver_12.1\common\bin\wlst.cmd" ( + SET WLST=%ORACLE_HOME%\wlserver_12.1\common\bin\wlst.cmd + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + GOTO found_wlst + ) + IF EXIST "%ORACLE_HOME%\wlserver\common\bin\wlst.cmd" ( + IF EXIST "%ORACLE_HOME%\wlserver\.product.properties" ( + @rem WLS 12.1.2 or WLS 12.1.3 + SET WLST=%ORACLE_HOME%\wlserver\common\bin\wlst.cmd + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + ) ELSE ( + @rem WLS 12.2.1+ + SET WLST=%ORACLE_HOME%\oracle_common\common\bin\wlst.cmd + SET WLST_EXT_CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + ) + GOTO found_wlst + ) +) + +IF NOT EXIST "%WLST%" ( + ECHO Unable to locate wlst.cmd script in ORACLE_HOME %ORACLE_HOME% >&2 + SET RETURN_CODE=98 + GOTO exit_script +) +:found_wlst + +SET LOG_CONFIG_CLASS=oracle.weblogic.deploy.logging.WLSDeployLoggingConfig +SET WLST_PROPERTIES=-Dcom.oracle.cie.script.throwException=true +SET "WLST_PROPERTIES=-Djava.util.logging.config.class=%LOG_CONFIG_CLASS% %WLST_PROPERTIES%" +SET "WLST_PROPERTIES=%WLST_PROPERTIES% %WLSDEPLOY_PROPERTIES%" + +IF NOT DEFINED WLSDEPLOY_LOG_PROPERTIES ( + SET WLSDEPLOY_LOG_PROPERTIES=%WLSDEPLOY_HOME%\etc\logging.properties +) +IF NOT DEFINED WLSDEPLOY_LOG_DIRECTORY ( + SET WLSDEPLOY_LOG_DIRECTORY=%WLSDEPLOY_HOME%\logs +) + +ECHO JAVA_HOME = %JAVA_HOME% +ECHO WLST_EXT_CLASSPATH = %WLST_EXT_CLASSPATH% +ECHO CLASSPATH = %CLASSPATH% +ECHO WLST_PROPERTIES = %WLST_PROPERTIES% + +SET PY_SCRIPTS_PATH=%WLSDEPLOY_HOME%\lib\python +ECHO %WLST% %PY_SCRIPTS_PATH%\variable_inject.py %* + +"%WLST%" "%PY_SCRIPTS_PATH%\variable_inject.py" %* + +SET RETURN_CODE=%ERRORLEVEL% +IF "%RETURN_CODE%" == "100" ( + GOTO usage +) +IF "%RETURN_CODE%" == "99" ( + GOTO usage +) +IF "%RETURN_CODE%" == "98" ( + ECHO. + ECHO variableInjector.cmd failed due to a parameter validation error >&2 + GOTO exit_script +) +IF "%RETURN_CODE%" == "2" ( + ECHO. + ECHO variableInjector.cmd failed ^(exit code = %RETURN_CODE%^) + GOTO exit_script +) +IF "%RETURN_CODE%" == "1" ( + ECHO. + ECHO variableInjector.cmd completed but with some issues ^(exit code = %RETURN_CODE%^) >&2 + GOTO exit_script +) +IF "%RETURN_CODE%" == "0" ( + ECHO. + ECHO variableInjector.cmd completed successfully ^(exit code = %RETURN_CODE%^) + GOTO exit_script +) +@rem Unexpected return code so just print the message and exit... +ECHO. +ECHO variableInjector.cmd failed ^(exit code = %RETURN_CODE%^) >&2 +GOTO exit_script + +:usage +ECHO. +ECHO Usage: %~nx0 [-help] +ECHO -oracle_home ^ +ECHO [-model_file ^] +ECHO [-archive_file ^] +ECHO [-variable_injector_file ^] +ECHO [-variable_properties_file ^] +ECHO [-domain_type ^] +ECHO [-wlst_path ^] +ECHO. +ECHO where: +ECHO oracle-home - the existing Oracle Home directory with the correct version for the model +ECHO. +ECHO model-file - the location of the model file in which variables will be injected. +ECHO If not specified, the tool will look for the model +ECHO in the archive file. Either the model_file or the archive_file argument +ECHO must be provided. +ECHO. +ECHO archive-file - the path to the archive file that contains a model in which the variables +ECHO will be injected. If the model-file argument is used, this argument will be +ECHO ignored. The archive file must contain a valid model. +ECHO. +ECHO variable_properties_file - the location of the property file in which to store any variable names injected +ECHO into the model. If this command line argument is not specified, the variable +ECHO will be located and named based on the model file or archive file name and +ECHO location. If the file exists, the file will be updated with new variable values. +ECHO. +ECHO variable-injector-file - the location of the variable injector file which contains the variable +ECHO injector keywords for this model injection run. If this argument is not provided, +ECHO the model_variable_injector.json file must exist in the lib directory in the +ECHO WLSDEPLOY_HOME location. +ECHO. +ECHO domain-type - the type of domain (e.g., WLS, JRF). +ECHO Used to locate wlst.cmd if wlst-path not specified +ECHO. +ECHO wlst-path - the Oracle Home subdirectory of the wlst.cmd +ECHO script to use (e.g., ^\soa) +ECHO. + +:exit_script +IF DEFINED USE_CMD_EXIT ( + EXIT %RETURN_CODE% +) ELSE ( + EXIT /B %RETURN_CODE% +) + +ENDLOCAL diff --git a/installer/src/main/bin/injectVariables.sh b/installer/src/main/bin/injectVariables.sh new file mode 100644 index 0000000000..c9a85de1ab --- /dev/null +++ b/installer/src/main/bin/injectVariables.sh @@ -0,0 +1,308 @@ +#!/bin/sh +# ***************************************************************************** +# injectVariables.sh +# +# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +# The Universal Permissive License (UPL), Version 1.0 +# +# NAME +# injectVariables.sh - WLS Deploy tool to inject variables into the model +# +# DESCRIPTION +# This script will inject variable tokens into the model and persist the variables to the +# indicated variable file. This can be run against a model that has injected variables. Any +# injected variables will not be replaced. If the existing variable file was provided, the +# new injected variables will be appended to the file. +# +# +# This script uses the following command-line arguments directly, the rest +# of the arguments are passed down to the underlying python program: +# +# - -oracle_home The directory of the existing Oracle Home to use. +# This directory must exist and it is the caller^'s +# responsibility to verify that it does. This +# argument is required. +# +# - -domain_type The type of domain to create. This argument is +# is optional. If not specified, it defaults to WLS. +# +# - -wlst_path The path to the Oracle Home product directory under +# which to find the wlst.cmd script. This is only +# needed for pre-12.2.1 upper stack products like SOA. +# +# For example, for SOA 12.1.3, -wlst_path should be +# specified as $ORACLE_HOME/soa +# +# This script uses the following variables: +# +# JAVA_HOME - The location of the JDK to use. The caller must set +# this variable to a valid Java 7 (or later) JDK. +# +# WLSDEPLOY_HOME - The location of the WLS Deploy installation. +# If the caller sets this, the callers location will be +# honored provided it is an existing directory. +# Otherwise, the location will be calculated from the +# location of this script. +# +# WLSDEPLOY_PROPERTIES - Extra system properties to pass to WLST. The caller +# can use this environment variable to add additional +# system properties to the WLST environment. +# + +usage() { + echo "" + echo "Usage: $1 [-help]" + echo " -oracle_home " + ecgi " -model_file ^ | -archive_file ^" + echo " [-variable_injector_file ^]" + echo " [-variable_keywords_file ^]" + echo " [-variable_properties_file ^]"" + echo " [-domain_type ]" + echo " [-wlst_path ]" + echo "" + echo " where:" + echo " oracle-home - the existing Oracle Home directory for the domain" + echo "" + echo " model-file - the location of the model file in which variables will be injected." + echo " If not specified, the tool will look for the model" + echo " in the archive file. Either the model_file or the archive_file argument must be provided." + echo "" + echo " archive-file - the path to the archive file that contains a model in which the variables" + echo " will be injected. If the model-file argument is used, this argument will be" + echo " ignored. The archive file must contain a valid model." + echo "" + echo " variable-injector-file - the location of the variable injector file which contains the variable" + echo " injector keywords for this model injection run. If this argument is not provided," + echo " the model_variable_injector.json file must exist in the lib directory in the" + echo " WLSDEPLOY_HOME location." + echo "" + echo " variable-keywords-file - this argument overrides the INSTALLED version of the allowed variable keywords" + echo " for the variable injector. This argument is for advanced usage only. The installed" + echo " keywords file is located in the lib directory of WLSDEPLOY_HOME location." + echo "" + echo " variable-file - the location of the property file in which to store any variable names injected" + echo " into the model. This argument overrides the value in the model injector file." + echo " If the variable file is not listed in the model injector file, and this command" + echo " line argument is not used, the variable properties will be located and named" + echo " based on the model file or archive file name and location." + echo " If the variable file exists, new variable values will be appended to the file." + echo "" + echo " domain-type - the type of domain (e.g., WLS, JRF)." + echo " Used to locate wlst.cmd if wlst-path not specified" + echo "" + echo " wlst-path - the Oracle Home subdirectory of the wlst.cmd" + echo " script to use (e.g., ^/soa)" + echo "" +} + +umask 27 + +WLSDEPLOY_PROGRAM_NAME="injectVariables"; export WLSDEPLOY_PROGRAM_NAME + +if [ "${WLSDEPLOY_HOME}" = "" ]; then + BASEDIR="$( cd "$( dirname $0 )" && pwd )" + WLSDEPLOY_HOME=`cd "${BASEDIR}/.." ; pwd` + export WLSDEPLOY_HOME +elif [ ! -d ${WLSDEPLOY_HOME} ]; then + echo "Specified WLSDEPLOY_HOME of ${WLSDEPLOY_HOME} does not exist" >&2 + exit 2 +fi + +# +# Make sure that the JAVA_HOME environment variable is set to point to a +# JDK 7 or higher JVM (and that it isn't OpenJDK). +# +if [ "${JAVA_HOME}" = "" ]; then + echo "Please set the JAVA_HOME environment variable to point to a Java 7 installation" >&2 + exit 2 +elif [ ! -d "${JAVA_HOME}" ]; then + echo "Your JAVA_HOME environment variable to points to a non-existent directory: ${JAVA_HOME}" >&2 + exit 2 +fi + +if [ -x "${JAVA_HOME}/bin/java" ]; then + JAVA_EXE=${JAVA_HOME}/bin/java +else + echo "Java executable at ${JAVA_HOME}/bin/java either does not exist or is not executable" >&2 + exit 2 +fi + +JVM_OUTPUT=`${JAVA_EXE} -version 2>&1` +case "${JVM_OUTPUT}" in + *OpenJDK*) + echo "JAVA_HOME ${JAVA_HOME} contains OpenJDK, which is not supported" >&2 + exit 2 + ;; +esac + +JVM_FULL_VERSION=`${JAVA_EXE} -fullversion 2>&1 | awk -F "\"" '{ print $2 }'` +JVM_VERSION=`echo ${JVM_FULL_VERSION} | awk -F "." '{ print $2 }'` + +if [ ${JVM_VERSION} -lt 7 ]; then + echo "You are using an unsupported JDK version ${JVM_FULL_VERSION}" >&2 + exit 2 +else + echo "JDK version is ${JVM_FULL_VERSION}" +fi + +# +# Check to see if no args were given and print the usage message +# +if [[ $# = 0 ]]; then + usage `basename $0` + exit 0 +fi + +SCRIPT_ARGS="$*" + +# +# Find the args required to determine the WLST script to run +# + +while [[ $# > 1 ]]; do + key="$1" + case $key in + -help) + usage `basename $0` + exit 0 + ;; + -oracle_home) + ORACLE_HOME="$2" + shift + ;; + -domain_type) + DOMAIN_TYPE="$2" + shift + ;; + -wlst_path) + WLST_PATH_DIR="$2" + shift + ;; + *) + # unknown option + ;; + esac + shift # past arg or value +done + +# +# Check for values of required arguments for this script to continue. +# The underlying WLST script has other required arguments. +# +if [ "${ORACLE_HOME}" = "" ]; then + echo "Required argument ORACLE_HOME not provided" >&2 + usage `basename $0` + exit 99 +elif [ ! -d ${ORACLE_HOME} ]; then + echo "The specified ORACLE_HOME does not exist: ${ORACLE_HOME}" >&2 + exit 98 +fi + +# +# If the WLST_PATH_DIR is specified, validate that it contains the wlst.cmd script +# +if [ "${WLST_PATH_DIR}" != "" ]; then + if [ ! -d ${WLST_PATH_DIR} ]; then + echo "WLST_PATH_DIR specified does not exist: ${WLST_PATH_DIR}" >&2 + exit 98 + fi + WLST=${WLST_PATH_DIR}/common/bin/wlst.sh + if [ ! -x "${WLST}" ]; then + echo "WLST executable ${WLST} not found under specified WLST_PATH_DIR: ${WLST_PATH_DIR}" >&2 + exit 98 + fi + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + WLST_EXT_CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export WLST_EXT_CLASSPATH +else + # + # Find the location for wlst.sh + # + WLST="" + USE_JRF_WLST=FALSE + if [ "${DOMAIN_TYPE}" = "WLS" ]; then + USE_JRF_WLST=FALSE + elif [ "${DOMAIN_TYPE}" = "RestrictedJRF" ]; then + USE_JRF_WLST=TRUE + elif [ "${DOMAIN_TYPE}" = "JRF" ]; then + USE_JRF_WLST=TRUE + else + echo "Domain type ${DOMAIN_TYPE} not recognized by shell script...assuming JRF is required" + fi + + if [ "${USE_JRF_WLST}" = "TRUE" ]; then + if [ -x ${ORACLE_HOME}/oracle_common/common/bin/wlst.sh ]; then + WLST=${ORACLE_HOME}/oracle_common/common/bin/wlst.sh + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + WLST_EXT_CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export WLST_EXT_CLASSPATH + fi + else + if [ -x ${ORACLE_HOME}/wlserver_10.3/common/bin/wlst.sh ]; then + WLST=${ORACLE_HOME}/wlserver_10.3/common/bin/wlst.sh + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + elif [ -x ${ORACLE_HOME}/wlserver_12.1/common/bin/wlst.sh ]; then + WLST=${ORACLE_HOME}/wlserver_12.1/common/bin/wlst.sh + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + elif [ -x ${ORACLE_HOME}/wlserver/common/bin/wlst.sh -a -f ${ORACLE_HOME}/wlserver/.product.properties ]; then + WLST=${ORACLE_HOME}/wlserver/common/bin/wlst.sh + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + else + WLST=${ORACLE_HOME}/oracle_common/common/bin/wlst.sh + WLST_EXT_CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export WLST_EXT_CLASSPATH + fi + fi + + if [ "${WLST}" = "" ]; then + echo "Unable to determine WLS version in ${ORACLE_HOME} to determine WLST shell script to call" >&2 + exit 98 + fi +fi + +LOG_CONFIG_CLASS=oracle.weblogic.deploy.logging.WLSDeployLoggingConfig +WLST_PROPERTIES=-Dcom.oracle.cie.script.throwException=true +WLST_PROPERTIES="-Djava.util.logging.config.class=${LOG_CONFIG_CLASS} ${WLST_PROPERTIES} ${WLSDEPLOY_PROPERTIES}" +export WLST_PROPERTIES + +if [ "${WLSDEPLOY_LOG_PROPERTIES}" = "" ]; then + WLSDEPLOY_LOG_PROPERTIES=${WLSDEPLOY_HOME}/etc/logging.properties; export WLSDEPLOY_LOG_PROPERTIES +fi + +if [ "${WLSDEPLOY_LOG_DIRECTORY}" = "" ]; then + WLSDEPLOY_LOG_DIRECTORY=${WLSDEPLOY_HOME}/logs; export WLSDEPLOY_LOG_DIRECTORY +fi + +echo "JAVA_HOME = ${JAVA_HOME}" +echo "WLST_EXT_CLASSPATH = ${WLST_EXT_CLASSPATH}" +echo "CLASSPATH = ${CLASSPATH}" +echo "WLST_PROPERTIES = ${WLST_PROPERTIES}" + +PY_SCRIPTS_PATH=${WLSDEPLOY_HOME}/lib/python +echo "${WLST} ${PY_SCRIPTS_PATH}/variable_inject.py ${SCRIPT_ARGS}" + +"${WLST}" "${PY_SCRIPTS_PATH}/variable_inject.py" ${SCRIPT_ARGS} + +RETURN_CODE=$? +if [ ${RETURN_CODE} -eq 100 ]; then + usage `basename $0` + RETURN_CODE=0 +elif [ ${RETURN_CODE} -eq 99 ]; then + usage `basename $0` + echo "" + echo "injectVariables.sh failed due to the usage error shown above" >&2 +elif [ ${RETURN_CODE} -eq 98 ]; then + echo "" + echo "injectVariables.sh failed due to a parameter validation error" >&2 +elif [ ${RETURN_CODE} -eq 2 ]; then + echo "" + echo "injectVariables.sh failed (exit code = ${RETURN_CODE})" >&2 +elif [ ${RETURN_CODE} -eq 1 ]; then + echo "" + echo "injectVariables.sh completed but with some issues (exit code = ${RETURN_CODE})" >&2 +elif [ ${RETURN_CODE} -eq 0 ]; then + echo "" + echo "injectVariables.sh completed successfully (exit code = ${RETURN_CODE})" +else + # Unexpected return code so just print the message and exit... + echo "" + echo "injectVariables.sh failed (exit code = ${RETURN_CODE})" >&2 +fi +exit ${RETURN_CODE} diff --git a/installer/src/main/lib/injectors/credentials.json b/installer/src/main/lib/injectors/credentials.json new file mode 100644 index 0000000000..b7f8cb3b41 --- /dev/null +++ b/installer/src/main/lib/injectors/credentials.json @@ -0,0 +1,143 @@ +{ + "ForeignJNDIProvider.User": {}, + "ForeignJNDIProvider.PasswordEncrypted": {}, + "JDBCSystemResource.JdbcResource.JDBCDriverParams.PasswordEncrypted": {}, + "JDBCSystemResource.JdbcResource.JDBCDriverParams.Properties[user].Value": {}, + "JDBCSystemResource.JdbcResource.JDBCOracleParams.OnsWalletPasswordEncrypted": {}, + "JMSBridgeDestination.UserName": {}, + "JMSBridgeDestination.UserPasswordEncrypted": {}, + "JMSSystemResource.JmsResource.ForeignServer.ForeignConnectionFactory.Username": {}, + "JMSSystemResource.JmsResource.ForeignServer.ForeignConnectionFactory.PasswordEncrypted": {}, + "JMSSystemResource.JmsResource.ForeignServer.JNDIPropertiesCredentialEncrypted": {}, + "JMSSystemResource.JmsResource.SAFRemoteContext.SAFLoginContext.PasswordEncrypted": {}, + "JMSSystemResource.JmsResource.SAFRemoteContext.SAFLoginContext.Username": {}, + "Machine.NodeManager.PasswordEncrypted": {}, + "Machine.NodeManager.UserName": {}, + "MailSession.SessionUsername": {}, + "MailSession.SessionPasswordEncrypted": {}, + "MailSession.Properties": { + "regexp": [ + { + "pattern": "mail.imap.user", + "suffix": "imap.user" + }, + { + "pattern": "mail.imap.password", + "suffix": "imap.password" + }, + { + "pattern": "mail.pop3.user", + "suffix": "pop3.user" + }, + { + "pattern": "mail.pop3.password", + "suffix": "pop3.password" + }, + { + "pattern": "mail.smtp.user", + "suffix": "smtp.user" + }, + { + "pattern": "mail.smtp.password", + "suffix": "smtp.password" + } + ] + }, + "Partition.ForeignJndiProviderOverride.User": {}, + "Partition.ForeignJndiProviderOverride.PasswordEncrypted": {}, + "Partition.JdbcSystemResourceOverride.PasswordEncrypted": {}, + "Partition.JdbcSystemResourceOverride.JdbcPropertyOverride[user].Value": {}, + "Partition.JmsSystemResourceOverride.ForeignServer.ForeignConnectionFactory.Username": {}, + "Partition.JmsSystemResourceOverride.ForeignServer.ForeignConnectionFactory.PasswordEncrypted": {}, + "Partition.JmsSystemResourceOverride.ForeignServer.JndiPropertiesCredentialEncrypted": {}, + "Partition.MailSessionOverride.SessionUsername": {}, + "Partition.MailSessionOverride.SessionPasswordEncrypted": {}, + "Security.User.Password": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.ActiveDirectoryAuthenticator.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.IPlanetAuthenticator.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.LDAPAuthenticator.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.LDAPX509IdentityAsserter.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.NovellAuthenticator.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OpenLDAPAuthenticator.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleInternetDirectoryAuthenticator.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleUnifiedDirectoryAuthenticator.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleVirtualDirectoryAuthenticator.CredentialEncrypted": {}, + "SecurityConfiguration.Realm.CredentialMapper.PKICredentialMapper.KeyStorePassPhraseEncrypted": {}, + "SecurityConfiguration.Realm.CredentialMapper.SAML2CredentialMapper.SigningKeyPassPhraseEncrypted": {}, + "SecurityConfiguration.Realm.CredentialMapper.SAMLCredentialMapperV2.SigningKeyPassPhraseEncrypted": {}, + "SecurityConfiguration.Realm.RDBMSSecurityStore.JNDIUsername": {}, + "SecurityConfiguration.Realm.RDBMSSecurityStore.JNDIPasswordEncrypted": {}, + "SecurityConfiguration.Realm.RDBMSSecurityStore.Username": {}, + "SecurityConfiguration.Realm.RDBMSSecurityStore.PasswordEncrypted": {}, + "SecurityConfiguration.CredentialEncrypted": {}, + "SecurityConfiguration.NodeManagerUsername": {}, + "SecurityConfiguration.NodeManagerPasswordEncrypted": {}, + "Server.FederationServices.SigningKeyAlias": {}, + "Server.FederationServices.SigningKeyPassPhraseEncrypted": {}, + "Server.FederationServices.SslClientIdentityAlias": {}, + "Server.FederationServices.SslClientIdentityPassPhraseEncrypted": {}, + "Server.NetworkAccessPoint.CustomIdentityKeyStorePassPhraseEncrypted": {}, + "Server.NetworkAccessPoint.CustomPrivateKeyAlias": {}, + "Server.NetworkAccessPoint.CustomPrivateKeyPassPhraseEncrypted": {}, + "Server.NetworkAccessPoint.OutboundPrivateKeyAlias": {}, + "Server.NetworkAccessPoint.OutboundPrivateKeyPassPhrase": {}, + "Server.NetworkAccessPoint.PrivateKeyAlias": {}, + "Server.NetworkAccessPoint.PrivateKeyPassPhrase": {}, + "Server.ServerStart.Username": {}, + "Server.ServerStart.PasswordEncrypted": {}, + "Server.SingleSignOnServices.BasicAuthUsername": {}, + "Server.SingleSignOnServices.BasicAuthPasswordEncrypted": {}, + "Server.SingleSignOnServices.SsoSigningKeyAlias": {}, + "Server.SingleSignOnServices.SsoSigningKeyPassPhraseEncrypted": {}, + "Server.SingleSignOnServices.TransportLayerSecurityKeyAlias": {}, + "Server.SingleSignOnServices.TransportLayerSecurityKeyPassPhraseEncrypted": {}, + "Server.SSL.ClientCertAlias": {}, + "Server.SSL.ClientCertPrivateKeyPassPhraseEncrypted": {}, + "Server.SSL.OutboundPrivateKeyAlias": {}, + "Server.SSL.OutboundPrivateKeyPassPhraseEncrypted": {}, + "Server.SSL.ServerPrivateKeyAlias": {}, + "Server.SSL.ServerPrivateKeyPassPhraseEncrypted": {}, + "Server.DefaultIIOPUser": {}, + "Server.DefaultIIOPPasswordEncrypted": {}, + "Server.DefaultTGIOPUser": {}, + "Server.DefaultTGIOPPasswordEncrypted": {}, + "Server.JavaStandardTrustKeyStorePassPhraseEncrypted": {}, + "Server.SystemPasswordEncrypted": {}, + "ServerTemplate.FederationServices.SigningKeyAlias": {}, + "ServerTemplate.FederationServices.SigningKeyPassPhraseEncrypted": {}, + "ServerTemplate.FederationServices.SslClientIdentityAlias": {}, + "ServerTemplate.FederationServices.SslClientIdentityPassPhraseEncrypted": {}, + "ServerTemplate.NetworkAccessPoint.CustomIdentityKeyStorePassPhraseEncrypted": {}, + "ServerTemplate.NetworkAccessPoint.CustomPrivateKeyAlias": {}, + "ServerTemplate.NetworkAccessPoint.CustomPrivateKeyPassPhraseEncrypted": {}, + "ServerTemplate.NetworkAccessPoint.OutboundPrivateKeyAlias": {}, + "ServerTemplate.NetworkAccessPoint.OutboundPrivateKeyPassPhrase": {}, + "ServerTemplate.NetworkAccessPoint.PrivateKeyAlias": {}, + "ServerTemplate.NetworkAccessPoint.PrivateKeyPassPhrase": {}, + "ServerTemplate.ServerStart.Username": {}, + "ServerTemplate.ServerStart.PasswordEncrypted": {}, + "ServerTemplate.SingleSignOnServices.BasicAuthUsername": {}, + "ServerTemplate.SingleSignOnServices.BasicAuthPasswordEncrypted": {}, + "ServerTemplate.SingleSignOnServices.SsoSigningKeyAlias": {}, + "ServerTemplate.SingleSignOnServices.SsoSigningKeyPassPhraseEncrypted": {}, + "ServerTemplate.SingleSignOnServices.TransportLayerSecurityKeyAlias": {}, + "ServerTemplate.SingleSignOnServices.TransportLayerSecurityKeyPassPhraseEncrypted": {}, + "ServerTemplate.SSL.ClientCertAlias": {}, + "ServerTemplate.SSL.ClientCertPrivateKeyPassPhraseEncrypted": {}, + "ServerTemplate.SSL.OutboundPrivateKeyAlias": {}, + "ServerTemplate.SSL.OutboundPrivateKeyPassPhraseEncrypted": {}, + "ServerTemplate.SSL.ServerPrivateKeyAlias": {}, + "ServerTemplate.SSL.ServerPrivateKeyPassPhraseEncrypted": {}, + "ServerTemplate.DefaultIIOPUser": {}, + "ServerTemplate.DefaultIIOPPasswordEncrypted": {}, + "ServerTemplate.DefaultTGIOPUser": {}, + "ServerTemplate.DefaultTGIOPPasswordEncrypted": {}, + "ServerTemplate.JavaStandardTrustKeyStorePassPhraseEncrypted": {}, + "ServerTemplate.SystemPasswordEncrypted": {}, + "UnixMachine.NodeManager.UserName": {}, + "UnixMachine.NodeManager.PasswordEncrypted": {}, + "WLDFSystemResource.WLDFResource.WatchNotification.RestNotification.HttpAuthenticationUserName": {}, + "WLDFSystemResource.WLDFResource.WatchNotification.RestNotification.HttpAuthenticationPasswordEncrypted": {} + +} + diff --git a/installer/src/main/lib/injectors/host.json b/installer/src/main/lib/injectors/host.json new file mode 100644 index 0000000000..bbe86c2a32 --- /dev/null +++ b/installer/src/main/lib/injectors/host.json @@ -0,0 +1,56 @@ +{ + "Cluster.FrontendHost": {}, + "Cluster.ClusterAddress": {}, + "Cluster.MulticastAddress": {}, + "Cluster.RemoteClusterAddress": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceAddressProvider.CoherenceSocketAddress.Address": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceClusterParams.CoherenceClusterWellKnownAddress.ListenAddress": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceClusterParams.MulticastListenAddress": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceClusterParams.UnicastListenAddress": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceFederationParams.RemoteParticipantHost": {}, + "CoherenceClusterSystemResource.FederationRemoteParticipantHost": {}, + "JDBCSystemResource.JdbcResource.JDBCOracleParams.OnsNodeList": {}, + "JMSSystemResource.JmsResource.Template.Multicast.MulticastAddress": {}, + "JMSSystemResource.JmsResource.Topic.Multicast.MulticastAddress": {}, + "JMSSystemResource.JmsResource.UniformDistributedTopic.Multicast.MulticastAddress": {}, + "Machine.NodeManager.ListenAddress": {}, + "Machine.Address": {}, + "NMProperties.ListenAddress": {}, + "SecurityConfiguration.CertRevoc.CrlCacheTypeLdapHostname": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.ActiveDirectoryAuthenticator.Host": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.IPlanetAuthenticator.Host": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.LDAPAuthenticator.Host": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.LDAPX509IdentityAsserter.Host": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.NovellAuthenticator.Host": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OpenLDAPAuthenticator.Host": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleInternetDirectoryAuthenticator.Host": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleUnifiedDirectoryAuthenticator.Host": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleVirtualDirectoryAuthenticator.Host": {}, + "Server.CoherenceMemberConfig.UnicastListenAddress": {}, + "Server.COM.NTAuthHost": {}, + "Server.NetworkAccessPoint.ClusterAddress": {}, + "Server.NetworkAccessPoint.ListenAddress": {}, + "Server.NetworkAccessPoint.ProxyAddress": {}, + "Server.NetworkAccessPoint.PublicAddress": {}, + "Server.JTAMigratableTarget.HostingServer": {}, + "Server.WebServer.FrontendHost": {}, + "Server.BuzzAddress": {}, + "Server.InterfaceAddress": {}, + "Server.ListenAddress": {}, + "ServerTemplate.CoherenceMemberConfig.UnicastListenAddress": {}, + "ServerTemplate.COM.NTAuthHost": {}, + "ServerTemplate.NetworkAccessPoint.ClusterAddress": {}, + "ServerTemplate.NetworkAccessPoint.ListenAddress": {}, + "ServerTemplate.NetworkAccessPoint.ProxyAddress": {}, + "ServerTemplate.NetworkAccessPoint.PublicAddress": {}, + "ServerTemplate.JTAMigratableTarget.HostingServer": {}, + "ServerTemplate.WebServer.FrontendHost": {}, + "ServerTemplate.BuzzAddress": {}, + "ServerTemplate.InterfaceAddress": {}, + "ServerTemplate.ListenAddress": {}, + "UnixMachine.NodeManager.ListenAddress": {}, + "VirtualHost.FrontendHost": {}, + "VirtualHost.VirtualHostName": {}, + "VirtualTarget.WebServer.FrontendHost": {}, + "VirtualTarget.HostName": {} +} diff --git a/installer/src/main/lib/injectors/port.json b/installer/src/main/lib/injectors/port.json new file mode 100644 index 0000000000..24db7e3a08 --- /dev/null +++ b/installer/src/main/lib/injectors/port.json @@ -0,0 +1,62 @@ +{ + "Cluster.FrontendHTTPPort": {}, + "Cluster.FrontendHTTPSPort": {}, + "Cluster.MulticastPort": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceAddressProvider.CoherenceSocketAddress.Port": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceClusterParams.CoherenceClusterWellKnownAddress.ListenPort": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceClusterParams.ClusterListenPort": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceClusterParams.MulticastListenPort": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceClusterParams.UnicastListenPort": {}, + "CoherenceClusterSystemResource.CoherenceResource.CoherenceFederationParams.RemoteCoherenceClusterListenPort": {}, + "CoherenceClusterSystemResource.FederationRemoteClusterListenPort": {}, + "JMSSystemResource.JmsResource.Template.Multicast.MulticastPort": {}, + "JMSSystemResource.JmsResource.Topic.Multicast.MulticastPort": {}, + "JMSSystemResource.JmsResource.UniformDistributedTopic.Multicast.MulticastPort": {}, + "Machine.NodeManager.ListenPort": {}, + "NMProperties.ListenPort": {}, + "SecurityConfiguration.CertRevoc.CrlCacheTypeLdapPort": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.ActiveDirectoryAuthenticator.Port": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.IPlanetAuthenticator.Port": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.LDAPAuthenticator.Port": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.LDAPX509IdentityAsserter.Port": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.NovellAuthenticator.Port": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OpenLDAPAuthenticator.Port": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleInternetDirectoryAuthenticator.Port": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleUnifiedDirectoryAuthenticator.Port": {}, + "SecurityConfiguration.Realm.AuthenticationProvider.OracleVirtualDirectoryAuthenticator.Port": {}, + "Server.CoherenceMemberConfig.UnicastListenPort": {}, + "Server.NetworkAccessPoint.ListenPort": {}, + "Server.NetworkAccessPoint.ProxyPort": {}, + "Server.NetworkAccessPoint.PublicPort": {}, + "Server.NetworkAccessPoint.SSLListenPort": {}, + "Server.SSL.ListenPort": {}, + "Server.WebServer.FrontendHTTPPort": {}, + "Server.WebServer.FrontendHTTPSPort": {}, + "Server.AdministrationPort": {}, + "Server.AdministrationPortEnabled": {}, + "Server.BuzzPort": {}, + "Server.ListenPort": {}, + "Server.ListenPortEnabled": {}, + "Server.ReplicationPorts": {}, + "ServerTemplate.CoherenceMemberConfig.UnicastListenPort": {}, + "ServerTemplate.NetworkAccessPoint.ListenPort": {}, + "ServerTemplate.NetworkAccessPoint.ProxyPort": {}, + "ServerTemplate.NetworkAccessPoint.PublicPort": {}, + "ServerTemplate.NetworkAccessPoint.SSLListenPort": {}, + "ServerTemplate.SSL.ListenPort": {}, + "ServerTemplate.WebServer.FrontendHTTPPort": {}, + "ServerTemplate.WebServer.FrontendHTTPSPort": {}, + "ServerTemplate.AdministrationPort": {}, + "ServerTemplate.AdministrationPortEnabled": {}, + "ServerTemplate.BuzzPort": {}, + "ServerTemplate.ListenPort": {}, + "ServerTemplate.ListenPortEnabled": {}, + "ServerTemplate.ReplicationPorts": {}, + "UnixMachine.NodeManager.ListenPort": {}, + "VirtualHost.FrontendHTTPPort": {}, + "VirtualHost.FrontendHTTPSPort": {}, + "VirtualTarget.WebServer.FrontendHTTPPort": {}, + "VirtualTarget.WebServer.FrontendHTTPSPort": {}, + "VirtualTarget.ExplicitPort": {}, + "VirtualTarget.PortOffset": {} +} diff --git a/installer/src/main/lib/injectors/target.json b/installer/src/main/lib/injectors/target.json new file mode 100644 index 0000000000..68683cfd5a --- /dev/null +++ b/installer/src/main/lib/injectors/target.json @@ -0,0 +1,40 @@ +{ + "AppDeployment.Target": {}, + "CoherenceClusterSystemResource.Target": {}, + "CoherenceClusterSystemResource.CoherenceCacheConfig.Target": {}, + "FileStore.Target": {}, + "ForeignJNDIProvider.Target": {}, + "JDBCStore.Target": {}, + "JDBCSystemResource.Target": {}, + "JMSServer.Target": {}, + "JMSServer.SubDeployment.Target": {}, + "Library.Target": {}, + "Library.SubDeployment.Target": {}, + "MailSession.Target": {}, + "MessagingBridge.Target": {}, + "PathService.Target": {}, + "ResourceGroup.Target": {}, + "SAFAgent.Target": {}, + "SelfTuning.Capacity.Target": {}, + "SelfTuning.ContextRequestClass.Target": {}, + "SelfTuning.ContextRequestClass.ContextCase.Target": {}, + "SelfTuning.FairShareRequestClass.Target": {}, + "SelfTuning.MaxThreadsConstraint.Target": {}, + "SelfTuning.MinThreadsConstraint.Target": {}, + "SelfTuning.ResponseTimeRequestClass.Target": {}, + "SelfTuning.WorkManager.Target": {}, + "Server.Cluster": {}, + "Server.DataSource.Target": {}, + "Server.TransactionLogJDBCStore.Target": {}, + "Server.WebServer.Target": {}, + "ServerTemplate.Cluster": {}, + "ServerTemplate.DataSource.Target": {}, + "ServerTemplate.TransactionLogJDBCStore.Target": {}, + "ServerTemplate.WebServer.Target": {}, + "ShutdownClass.Target": {}, + "StartupClass.Target": {}, + "VirtualHost.Target": {}, + "VirtualTarget.Target": {}, + "VirtualTarget.WebServer.Target": {}, + "WLDFSystemResource.Target": {} +} diff --git a/installer/src/main/lib/injectors/topology.json b/installer/src/main/lib/injectors/topology.json new file mode 100644 index 0000000000..183ae2bb65 --- /dev/null +++ b/installer/src/main/lib/injectors/topology.json @@ -0,0 +1,31 @@ +{ + "Cluster.ClusterAddress": {}, + "Cluster.ClusterMessagingMode": {}, + "Cluster.MulticastAddress": {}, + "Cluster.MulticastPort": {}, + "Server.Log.LogFileRotationDir": {}, + "Server.NetworkAccessPoint.HostnameVerificationIgnored": {}, + "Server.NetworkAccessPoint.HostnameVerifier": {}, + "Server.SSL.Enabled": {}, + "Server.SSL.ListenPort": {}, + "Server.ListenAddress": {}, + "Server.ListenPort": {}, + "Server.ListenPortEnabled": {}, + "Server.Machine": {}, + "Server.ServerTemplate": {}, + "Server.SystemPasswordEncrypted": {}, + "Server.TunnelingEnabled": {}, + "Server.UseFusionForLLR": {}, + "Machine.Address": {}, + "Machine.NodeManager.ListenAddress": {}, + "Machine.NodeManager.ListenPort": {}, + "Machine.NodeManager.NodeManagerHome": {}, + "Machine.NodeManager.PasswordEncrypted": {}, + "Machine.NodeManager.UserName": {}, + "UnixMachine.Address": {}, + "UnixMachine.NodeManager.ListenAddress": {}, + "UnixMachine.NodeManager.ListenPort": {}, + "UnixMachine.NodeManager.NodeManagerHome": {}, + "UnixMachine.NodeManager.PasswordEncrypted": {}, + "UnixMachine.NodeManager.UserName": {} +} diff --git a/installer/src/main/lib/injectors/url.json b/installer/src/main/lib/injectors/url.json new file mode 100644 index 0000000000..efd6a7e847 --- /dev/null +++ b/installer/src/main/lib/injectors/url.json @@ -0,0 +1,24 @@ +{ + "ForeignJNDIProvider.ProviderUrl": {}, + "JDBCSystemResource.JdbcResource.JDBCDriverParams.URL": {}, + "JMSBridgeDestination.ConnectionURL": {}, + "JMSSystemResource.JmsResource.ForeignServer.ConnectionURL": {}, + "JMSSystemResource.JmsResource.SAFRemoteContext.SAFLoginContext.LoginURL": {}, + "Partition.ForeignJndiProviderOverride.ProviderUrl": {}, + "SecurityConfiguration.CertRevoc.CertRevocCa.CrlDpUrl": {}, + "SecurityConfiguration.CertRevoc.CertRevocCa.OcspResponderUrl": {}, + "SecurityConfiguration.Realm.RDBMSSecurityStore.ConnectionURL": {}, + "Server.FederationServices.SourceSiteUrl": {}, + "Server.ServerDebug.BugReportServiceWsdlUrl": {}, + "Server.SingleSignOnServices.DefaultUrl": {}, + "Server.SingleSignOnServices.LoginUrl": {}, + "Server.SingleSignOnServices.OrganizationUrl": {}, + "Server.SingleSignOnServices.PublishedSiteUrl": {}, + "ServerTemplate.FederationServices.SourceSiteUrl": {}, + "ServerTemplate.ServerDebug.BugReportServiceWsdlUrl": {}, + "ServerTemplate.SingleSignOnServices.DefaultUrl": {}, + "ServerTemplate.SingleSignOnServices.LoginUrl": {}, + "ServerTemplate.SingleSignOnServices.OrganizationUrl": {}, + "ServerTemplate.SingleSignOnServices.PublishedSiteUrl": {}, + "WLDFSystemResource.WLDFResource.WatchNotification.RestNotification.EndpointUrl": {} +} diff --git a/installer/src/main/lib/variable_keywords.json b/installer/src/main/lib/variable_keywords.json new file mode 100644 index 0000000000..b340bcf2f4 --- /dev/null +++ b/installer/src/main/lib/variable_keywords.json @@ -0,0 +1,8 @@ +{ + "CREDENTIALS": "credentials.json", + "PORT": "port.json", + "HOST": "host.json", + "URL": "url.json", + "TARGET": "target.json", + "TOPOLOGY": "topology.json" +} diff --git a/installer/src/main/samples/custom_injector.json b/installer/src/main/samples/custom_injector.json new file mode 100644 index 0000000000..75b0a04846 --- /dev/null +++ b/installer/src/main/samples/custom_injector.json @@ -0,0 +1,21 @@ +{ + "UnixMachine.NodeManager.ListenAddress": {}, + "UnixMachine.NodeManager.ListenPort": {}, + "JDBCSystemResource.JdbcResource.JDBCDriverParams.URL": + { + "regexp": [ + { + "pattern": "(?<=PORT=)[\\w.-]+(?=\\))", + "suffix": "Port" + }, + { + "pattern": "(?<=HOST=)[\\w.-]+(?=\\))", + "suffix": "Host" + } + ] + }, + "Server[MANAGED_SERVERS].SSL.Enabled": {}, + "Server[ADMIN_SERVER].SSL.HostnameVerificationIgnored": { + "force": true + } +} diff --git a/installer/src/main/samples/model_variable_injector.json b/installer/src/main/samples/model_variable_injector.json new file mode 100644 index 0000000000..3b38c47e36 --- /dev/null +++ b/installer/src/main/samples/model_variable_injector.json @@ -0,0 +1,6 @@ +{ + "CREDENTIALS": {}, + "CUSTOM": { + "file-list": [ "@@WLSDEPLOY@@/samples/custom_injector.json" ] + } +}