diff --git a/operator/pom.xml b/operator/pom.xml
index 5858395e01c..3816f0008b9 100644
--- a/operator/pom.xml
+++ b/operator/pom.xml
@@ -231,14 +231,36 @@
java
package
+
+ oracle.kubernetes.operator.helpers.CrdHelper
+
+ ${project.basedir}/../kubernetes/crd/domain-crd.yaml
+
+
+
+
+ test-python-scripts
+ test
+
+ exec
+
+
+ ${skip.unit.tests}
+ python
+ src/test/python
+
+ ${project.basedir}/src/main/resources/scripts
+ sample-domain1
+
+
+ -B
+ -m
+ unittest
+ discover
+
+
-
- oracle.kubernetes.operator.helpers.CrdHelper
-
- ${project.basedir}/../kubernetes/crd/domain-crd.yaml
-
-
diff --git a/operator/src/main/java/oracle/kubernetes/operator/helpers/JobHelper.java b/operator/src/main/java/oracle/kubernetes/operator/helpers/JobHelper.java
index 81c1f05bd6e..8f527c4a336 100644
--- a/operator/src/main/java/oracle/kubernetes/operator/helpers/JobHelper.java
+++ b/operator/src/main/java/oracle/kubernetes/operator/helpers/JobHelper.java
@@ -314,7 +314,6 @@ List getConfiguredEnvVars(TuningParameters tuningParameters) {
Long.toString(getDomain().getWDTSetServerGroupsTimeoutMillis()));
}
-
String dataHome = getDataHome();
if (dataHome != null && !dataHome.isEmpty()) {
addEnvVar(vars, ServerEnvVars.DATA_HOME, dataHome);
diff --git a/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java b/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java
index 3e534414f76..c7bcbf27b31 100644
--- a/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java
+++ b/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java
@@ -61,6 +61,7 @@
import oracle.kubernetes.operator.work.Step;
import oracle.kubernetes.weblogic.domain.model.Domain;
import oracle.kubernetes.weblogic.domain.model.DomainStatus;
+import oracle.kubernetes.weblogic.domain.model.IntrospectorJobEnvVars;
import oracle.kubernetes.weblogic.domain.model.ServerEnvVars;
import oracle.kubernetes.weblogic.domain.model.ServerSpec;
import oracle.kubernetes.weblogic.domain.model.Shutdown;
@@ -631,6 +632,11 @@ private void updateEnv(List env) {
updateEnvForShutdown(env);
updateEnvForStartupMode(env);
defineConfigOverride(env);
+ updateEnvWithDomainSourceType(env);
+ }
+
+ private void updateEnvWithDomainSourceType(List env) {
+ addDefaultEnvVarIfMissing(env, IntrospectorJobEnvVars.DOMAIN_SOURCE_TYPE, getDomainHomeSourceType().toString());
}
private void updateEnvForShutdown(List env) {
diff --git a/operator/src/main/resources/scripts/introspectDomain.py b/operator/src/main/resources/scripts/introspectDomain.py
index aec9b2c3bad..f54faa823a6 100644
--- a/operator/src/main/resources/scripts/introspectDomain.py
+++ b/operator/src/main/resources/scripts/introspectDomain.py
@@ -767,6 +767,10 @@ def addNetworkAccessPoint(self, server, nap, is_server_template):
nap_protocol = getNAPProtocol(nap, server, self.env.getDomain(), is_server_template)
if istio_enabled == 'true':
+ name = nap.getName()
+ if name.startswith('http-') or name.startswith('tcp-') or name.startswith('tls-') or name.startswith('https-'):
+ # skip istio ports already defined by WDT filtering for MII
+ return
http_protocol = [ 'http' ]
https_protocol = ['https','admin']
tcp_protocol = [ 't3', 'snmp', 'ldap', 'cluster-broadcast', 'iiop', 'sip']
@@ -1606,10 +1610,11 @@ def introspect(self):
tg = TopologyGenerator(self.env)
if tg.validate():
- SitConfigGenerator(self.env).generate()
+ DOMAIN_SOURCE_TYPE = self.env.getEnvOrDef("DOMAIN_SOURCE_TYPE", None)
+ if DOMAIN_SOURCE_TYPE != "FromModel":
+ SitConfigGenerator(self.env).generate()
BootPropertiesGenerator(self.env).generate()
UserConfigAndKeyGenerator(self.env).generate()
- DOMAIN_SOURCE_TYPE = self.env.getEnvOrDef("DOMAIN_SOURCE_TYPE", None)
if DOMAIN_SOURCE_TYPE == "FromModel":
trace("cfgmap write primordial_domain")
diff --git a/operator/src/main/resources/scripts/livenessProbe.sh b/operator/src/main/resources/scripts/livenessProbe.sh
index 66d52641652..fd0b4f5ba1c 100755
--- a/operator/src/main/resources/scripts/livenessProbe.sh
+++ b/operator/src/main/resources/scripts/livenessProbe.sh
@@ -102,9 +102,11 @@ if [ $? != 0 ]; then
exit $RETVAL
fi
-copySitCfgWhileRunning /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig 'Sit-Cfg-CFG--'
-copySitCfgWhileRunning /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/jms 'Sit-Cfg-JMS--'
-copySitCfgWhileRunning /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/jdbc 'Sit-Cfg-JDBC--'
-copySitCfgWhileRunning /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/diagnostics 'Sit-Cfg-WLDF--'
+if [ ${DOMAIN_SOURCE_TYPE} != "FromModel" ]; then
+ copySitCfgWhileRunning /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig 'Sit-Cfg-CFG--'
+ copySitCfgWhileRunning /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/jms 'Sit-Cfg-JMS--'
+ copySitCfgWhileRunning /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/jdbc 'Sit-Cfg-JDBC--'
+ copySitCfgWhileRunning /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/diagnostics 'Sit-Cfg-WLDF--'
+fi
exit 0
diff --git a/operator/src/main/resources/scripts/model-filters.json b/operator/src/main/resources/scripts/model-filters.json
index 0b55aa179ab..dff0b7ed97e 100644
--- a/operator/src/main/resources/scripts/model-filters.json
+++ b/operator/src/main/resources/scripts/model-filters.json
@@ -7,5 +7,9 @@
"discover": [
],
"update": [
+ { "name": "update_mii_filter", "path": "/u01/wdt/weblogic-deploy/lib/model_wdt_mii_filter.py" }
+ ],
+ "validate": [
+ { "name": "validate_mii_filter", "path": "/u01/wdt/weblogic-deploy/lib/model_wdt_mii_filter.py" }
]
}
\ No newline at end of file
diff --git a/operator/src/main/resources/scripts/modelInImage.sh b/operator/src/main/resources/scripts/modelInImage.sh
index 632ec986db7..5c9c70fd1bc 100755
--- a/operator/src/main/resources/scripts/modelInImage.sh
+++ b/operator/src/main/resources/scripts/modelInImage.sh
@@ -37,6 +37,7 @@ WDT_OUTPUT="/tmp/wdt_output.log"
WDT_BINDIR="${WDT_ROOT}/bin"
WDT_FILTER_JSON="/weblogic-operator/scripts/model-filters.json"
WDT_CREATE_FILTER="/weblogic-operator/scripts/model-wdt-create-filter.py"
+WDT_MII_FILTER="/weblogic-operator/scripts/model_wdt_mii_filter.py"
UPDATE_RCUPWD_FLAG=""
WLSDEPLOY_PROPERTIES="${WLSDEPLOY_PROPERTIES} -Djava.security.egd=file:/dev/./urandom"
ARCHIVE_ZIP_CHANGED=0
@@ -319,9 +320,9 @@ function createWLDomain() {
fi
# copy the filter related files to the wdt lib
-
- cp ${WDT_FILTER_JSON} ${WDT_ROOT}/lib/model_filters.json
- cp ${WDT_CREATE_FILTER} ${WDT_ROOT}/lib
+ cp ${WDT_FILTER_JSON} ${WDT_ROOT}/lib/model_filters.json || logSevereAndExit ${WDT_FILTER_JSON}
+ cp ${WDT_CREATE_FILTER} ${WDT_ROOT}/lib || logSevereAndExit ${WDT_CREATE_FILTER}
+ cp ${WDT_MII_FILTER} ${WDT_ROOT}/lib || logSevereAndExit ${WDT_MII_FILTER}
# check to see if any model including changed (or first model in image deploy)
# if yes. then run create domain again
@@ -793,8 +794,14 @@ function generateMergedModel() {
export __WLSDEPLOY_STORE_MODEL__="${NEW_MERGED_MODEL}"
- ${WDT_BINDIR}/validateModel.sh -oracle_home ${ORACLE_HOME} ${model_list} \
- ${archive_list} ${variable_list} -domain_type ${WDT_DOMAIN_TYPE} > ${WDT_OUTPUT} 2>&1
+ local wdtArgs=""
+ wdtArgs+=" -oracle_home ${ORACLE_HOME}"
+ wdtArgs+=" ${model_list} ${archive_list} ${variable_list}"
+ wdtArgs+=" -domain_type ${WDT_DOMAIN_TYPE}"
+
+ trace "About to call '${WDT_BINDIR}/validateModel.sh ${wdtArgs}'."
+
+ ${WDT_BINDIR}/validateModel.sh ${wdtArgs} > ${WDT_OUTPUT} 2>&1
ret=$?
if [ $ret -ne 0 ]; then
trace SEVERE "Model in Image: the WDT validate model tool detected an error with the fully merged model:"
@@ -917,8 +924,16 @@ function wdtUpdateModelDomain() {
# make sure wdt create write out the merged model to a file in the root of the domain
export __WLSDEPLOY_STORE_MODEL__=1
- ${WDT_BINDIR}/updateDomain.sh -oracle_home ${ORACLE_HOME} -domain_home ${DOMAIN_HOME} $model_list \
- ${archive_list} ${variable_list} -domain_type ${WDT_DOMAIN_TYPE} ${UPDATE_RCUPWD_FLAG} > ${WDT_OUTPUT} 2>&1
+ local wdtArgs=""
+ wdtArgs+=" -oracle_home ${ORACLE_HOME}"
+ wdtArgs+=" -domain_home ${DOMAIN_HOME}"
+ wdtArgs+=" ${model_list} ${archive_list} ${variable_list}"
+ wdtArgs+=" -domain_type ${WDT_DOMAIN_TYPE}"
+ wdtArgs+=" ${UPDATE_RCUPWD_FLAG}"
+
+ trace "About to call '${WDT_BINDIR}/updateDomain.sh ${wdtArgs}'."
+
+ ${WDT_BINDIR}/updateDomain.sh ${wdtArgs} > ${WDT_OUTPUT} 2>&1
ret=$?
if [ $ret -ne 0 ]; then
@@ -1271,3 +1286,8 @@ function stop_trap() {
function cleanup_mii() {
rm -f /tmp/*.md5 /tmp/*.gz /tmp/*.ini /tmp/*.json
}
+
+function logSevereAndExit() {
+ trace SEVERE "cp '$1' failed"
+ exitOrLoop
+}
diff --git a/operator/src/main/resources/scripts/model_wdt_mii_filter.py b/operator/src/main/resources/scripts/model_wdt_mii_filter.py
new file mode 100644
index 00000000000..7cecd6985ac
--- /dev/null
+++ b/operator/src/main/resources/scripts/model_wdt_mii_filter.py
@@ -0,0 +1,598 @@
+# Copyright (c) 2018, 2021, Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+#
+# ------------
+# Description:
+# ------------
+# This is a model-in-image WDT filter for overriding WLS configuration, it
+# replaces 'situational configuration overrides'.
+#
+# This code is used by the operator during introspection for MII to manipulate
+# the domain model. It generates domain configuration information that's
+# useful for running the domain, setting up its networking, and for overriding
+# specific parts of its configuration so that it can run in k8s.
+#
+# For more details, see the Model Filters description in the WebLogic Deploy
+# Tooling in Github.
+#
+# ---------------------
+# Prerequisites/Inputs:
+# ---------------------
+#
+# A domain model as a Jython dictionary.
+#
+# The following env vars are required:
+# DOMAIN_UID - completely unique id for this domain
+# DOMAIN_HOME - path for the domain configuration
+# LOG_HOME - path to override WebLogic server log locations
+# CREDENTIALS_SECRET_NAME - name of secret containing credentials
+#
+# The following env vars are optional:
+# ACCESS_LOG_IN_LOG_HOME - HTTP access log files will be written to
+# the logHome directory.
+# DATA_HOME - in-pod location for data storage of default and custom file
+# stores.
+# CREDENTIALS_SECRET_PATH - directory path to secret containing credentials
+#
+# ---------------------------------
+# Result
+# ---------------------------------
+#
+# The configuration overrides are directly modified in the domain model and
+# include listen addresses, log file locations, etc. The WebLogic Deploy
+# Tooling will then generate/update the domain with the appropriate
+# configuration.
+#
+
+
+import inspect
+import os
+import sys
+
+tmp_callerframerecord = inspect.stack()[0] # 0 represents this line # 1 represents line at caller
+tmp_info = inspect.getframeinfo(tmp_callerframerecord[0])
+tmp_scriptdir=os.path.dirname(tmp_info[0])
+sys.path.append(tmp_scriptdir)
+
+env = None
+
+class OfflineWlstEnv(object):
+
+ def open(self, model):
+
+ self.model = model
+ # before doing anything, get each env var and verify it exists
+
+ self.DOMAIN_UID = self.getEnv('DOMAIN_UID')
+ self.DOMAIN_HOME = self.getEnv('DOMAIN_HOME')
+ self.LOG_HOME = self.getEnv('LOG_HOME')
+ self.ACCESS_LOG_IN_LOG_HOME = self.getEnvOrDef('ACCESS_LOG_IN_LOG_HOME', 'true')
+ self.DATA_HOME = self.getEnvOrDef('DATA_HOME', "")
+ self.CREDENTIALS_SECRET_NAME = self.getEnv('CREDENTIALS_SECRET_NAME')
+
+ # initialize globals
+ self.CREDENTIALS_SECRET_PATH = self.getEnvOrDef('CREDENTIALS_SECRET_PATH', '/weblogic-operator/secrets')
+ self.TOPOLOGY_YAML_PATH = '/weblogic-operator/introspectormii/topology.yaml'
+ self.DOMAIN_NAME = None
+
+ if model and 'topology' in model:
+ self.DOMAIN_NAME = model['topology']['Name']
+
+ if self.DOMAIN_NAME is None and os.path.exists(self.TOPOLOGY_YAML_PATH):
+ self.readDomainNameFromTopologyYaml(self.TOPOLOGY_YAML_PATH)
+
+ def readDomainNameFromTopologyYaml(self, path):
+ file = open(path, 'r')
+ content = file.readlines()
+ file.close()
+ # access line containing domain name and strip leading and trailing spaces
+ line = content[2].strip()
+ # create key-value pair (e.g. name="sample-domain1")
+ (key, val) = line.split()
+ if key == 'name:':
+ # strip leading and trailing double quotes from value
+ self.DOMAIN_NAME = val.strip('"')
+
+ def getDomainName(self):
+ return self.DOMAIN_NAME
+
+ def getDomainUID(self):
+ return self.DOMAIN_UID
+
+ def getDomainHome(self):
+ return self.DOMAIN_HOME
+
+ def getDomainLogHome(self):
+ return self.LOG_HOME
+
+ def getDataHome(self):
+ return self.DATA_HOME
+
+ def isAccessLogInLogHome(self):
+ return self.ACCESS_LOG_IN_LOG_HOME == 'true'
+
+ def readFile(self, path):
+ file = open(path, 'r')
+ contents = file.read()
+ file.close()
+ return contents
+
+ def getEnv(self, name):
+ val = os.getenv(name)
+ if val is None or val == "null":
+ print("SEVERE: Env var %s not set." % name)
+ sys.exit(1)
+ return val
+
+ def getEnvOrDef(self, name, deflt):
+ val = os.getenv(name)
+ if val == None or val == "null" or len(val) == 0:
+ return deflt
+ return val
+
+ def toDNS1123Legal(self, address):
+ return address.lower().replace('_','-')
+
+ def getModel(self):
+ return self.model
+
+ def wlsVersionEarlierThan(self, version):
+ # unconventional import within function definition for unit testing
+ from weblogic.management.configuration import LegalHelper
+ return LegalHelper.versionEarlierThan("14.1.2.0", version)
+
+class SecretManager(object):
+
+ def __init__(self, env):
+ self.env = env
+
+ def readCredentialsSecret(self, key):
+ path = self.env.CREDENTIALS_SECRET_PATH + '/' + key
+ return self.env.readFile(path)
+
+
+def filter_model(model):
+ if model is not None:
+ if getOfflineWlstEnv() is None:
+ initOfflineWlstEnv(model)
+
+ initSecretManager(env)
+
+ if model and 'resources' in model:
+ customizeCustomFileStores(model)
+
+ if model and 'topology' in model:
+ topology = model['topology']
+ customizeNodeManagerCreds(topology)
+ customizeDomainLogPath(topology)
+ if 'Server' in topology:
+ customizeServers(model)
+
+ if 'ServerTemplate' in topology:
+ customizeServerTemplates(model)
+
+
+def initOfflineWlstEnv(model):
+ global env
+ env = OfflineWlstEnv()
+ env.open(model)
+
+
+def getOfflineWlstEnv():
+ if env is not None:
+ return env
+ return None
+
+
+def setOfflineWlstEnv(offlineWlstEnv):
+ env = offlineWlstEnv
+
+def initSecretManager(env):
+ global secret_manager
+ secret_manager = SecretManager(env)
+
+def customizeServerTemplates(model):
+ topology = model['topology']
+ if 'ServerTemplate' not in topology:
+ return
+
+ serverTemplates = topology['ServerTemplate']
+ template_names = serverTemplates.keys()
+ if template_names is not None:
+ for template_name in template_names:
+ template = serverTemplates[template_name]
+ cluster_name = getClusterNameOrNone(template)
+ if cluster_name is not None:
+ customizeServerTemplate(topology, template)
+
+
+def customizeServerTemplate(topology, template):
+ server_name_prefix = getServerNamePrefix(topology, template)
+ domain_uid = env.getDomainUID()
+ customizeLog(server_name_prefix + "${id}", template)
+ customizeAccessLog(server_name_prefix + "${id}", template)
+ customizeDefaultFileStore(template)
+ listen_address=env.toDNS1123Legal(domain_uid + "-" + server_name_prefix + "${id}")
+ setServerListenAddress(template, listen_address)
+ customizeNetworkAccessPoints(template, listen_address)
+ customizeManagedIstioNetworkAccessPoint(template, listen_address)
+
+
+def getServerNamePrefix(topology, template):
+ server_name_prefix = None
+ cluster_name = getClusterNameOrNone(template)
+ if cluster_name is not None:
+ cluster = getClusterOrNone(topology, cluster_name)
+ if cluster is not None:
+ dynamicServer = getDynamicServerOrNone(cluster)
+ if dynamicServer is not None:
+ server_name_prefix = getDynamicServerPropertyOrNone(dynamicServer, 'ServerNamePrefix')
+
+ return server_name_prefix
+
+
+def customizeNodeManagerCreds(topology):
+ username = getSecretManager().readCredentialsSecret('username')
+ pwd = getSecretManager().readCredentialsSecret('password')
+
+ if not ('SecurityConfiguration' in topology):
+ topology['SecurityConfiguration'] = {}
+
+ topology['SecurityConfiguration']['NodeManagerUsername'] = username
+ topology['SecurityConfiguration']['NodeManagerPasswordEncrypted'] = pwd
+
+
+def customizeDomainLogPath(topology):
+ customizeLog(env.getDomainName(), topology)
+
+
+def customizeLog(name, topologyOrServer):
+ if name is None:
+ # domain name is req'd to create domain log configuration.
+ # Missing domain name indicates our model is a fragment
+ return
+
+ logs_dir = env.getDomainLogHome()
+ if logs_dir is None or len(logs_dir) == 0:
+ return
+
+ if 'Log' not in topologyOrServer:
+ topologyOrServer['Log'] = {}
+
+ topologyOrServer['Log']['FileName'] = logs_dir + "/" + name + ".log"
+
+
+def customizeCustomFileStores(model):
+ customizeFileStores(model['resources'])
+
+
+def customizeFileStores(resources):
+ data_dir = env.getDataHome()
+ if data_dir is None or len(data_dir) == 0:
+ # do not override if dataHome not specified or empty ("")
+ return
+
+ if 'FileStore' not in resources:
+ return
+
+ filestores = resources['FileStore']
+ names = filestores.keys()
+ for name in names:
+ filestore = filestores[name]
+ customizeFileStore(filestore, data_dir)
+
+
+def customizeFileStore(filestore, data_dir):
+ filestore['Directory'] = data_dir
+
+
+def customizeServers(model):
+ if 'Server' not in model['topology']:
+ return
+
+ servers = model['topology']['Server']
+ names = servers.keys()
+ for name in names:
+ server = servers[name]
+ customizeServer(server, name)
+
+
+def customizeServer(server, name):
+ listen_address=env.toDNS1123Legal(env.getDomainUID() + "-" + name)
+ customizeLog(name, server)
+ customizeAccessLog(name, server)
+ customizeDefaultFileStore(server)
+ setServerListenAddress(server, listen_address)
+ customizeNetworkAccessPoints(server,listen_address)
+ customizeServerIstioNetworkAccessPoint(server, listen_address)
+
+
+def getAdministrationPort(server, topology):
+ port = 0
+ if 'AdministrationPort' in server:
+ port = int(server['AdministrationPort'])
+ if port == 0 and 'AdministrationPort' in topology:
+ port = int(topology['AdministrationPort'])
+ return port
+
+
+def isAdministrationPortEnabledForServer(server, topology):
+ administrationPortEnabled = False
+ if 'AdministrationPortEnabled' in server:
+ administrationPortEnabled = server['AdministrationPortEnabled'] == 'true'
+ else:
+ administrationPortEnabled = isAdministrationPortEnabledForDomain(topology)
+ return administrationPortEnabled
+
+
+def isAdministrationPortEnabledForDomain(topology):
+ administrationPortEnabled = False
+
+ if 'AdministrationPortEnabled' in topology:
+ administrationPortEnabled = topology['AdministrationPortEnabled'] == 'true'
+ else:
+ # AdministrationPortEnabled is not explicitly set so going with the default
+ # Starting with 14.1.2.0, the domain's AdministrationPortEnabled default is derived from the domain's SecureMode
+ administrationPortEnabled = isSecureModeEnabledForDomain(topology)
+ return administrationPortEnabled
+
+
+# Derive the default value for SecureMode of a domain
+def isSecureModeEnabledForDomain(topology):
+ secureModeEnabled = False
+ if 'SecurityConfiguration' in topology and 'SecureMode' in topology['SecurityConfiguration'] and 'SecureModeEnabled' in topology['SecurityConfiguration']['SecureMode']:
+ secureModeEnabled = topology['SecurityConfiguration']['SecureMode']['SecureModeEnabled'] == 'true'
+ else:
+ is_production_mode_enabled = False
+ if 'ProductionModeEnabled' in topology:
+ is_production_mode_enabled = topology['ProductionModeEnabled'] == 'true'
+ secureModeEnabled = is_production_mode_enabled and not env.wlsVersionEarlierThan("14.1.2.0")
+ return secureModeEnabled
+
+
+def getSSLOrNone(server):
+ if 'SSL' not in server:
+ return None
+
+ return server['SSL']
+
+
+def _writeIstioNAP(name, server, listen_address, listen_port, protocol, http_enabled="true"):
+
+ if 'NetworkAccessPoint' not in server:
+ server['NetworkAccessPoint'] = {}
+
+ naps = server['NetworkAccessPoint']
+ if name not in naps:
+ naps[name] = {}
+
+ nap = naps[name]
+ nap['Protocol'] = protocol
+ nap['ListenAddress'] = '127.0.0.1'
+ nap['PublicAddress'] = '%s.%s' % (listen_address, env.getEnvOrDef("ISTIO_POD_NAMESPACE", "default"))
+ nap['ListenPort'] = listen_port
+ nap['HttpEnabledForThisProtocol'] = http_enabled
+ nap['TunnelingEnabled'] = 'false'
+ nap['OutboundEnabled'] = 'true'
+ nap['Enabled'] = 'true'
+
+
+def customizeServerIstioNetworkAccessPoint(server, listen_address):
+ istio_enabled = env.getEnvOrDef("ISTIO_ENABLED", "false")
+ if istio_enabled == 'false':
+ return
+ istio_readiness_port = env.getEnvOrDef("ISTIO_READINESS_PORT", None)
+ if istio_readiness_port is None:
+ return
+ admin_server_port = server['ListenPort']
+ # readiness probe
+ _writeIstioNAP(name='http-probe', server=server, listen_address=listen_address,
+ listen_port=istio_readiness_port, protocol='http', http_enabled="true")
+
+ # Generate NAP for each protocols
+ _writeIstioNAP(name='tcp-ldap', server=server, listen_address=listen_address,
+ listen_port=admin_server_port, protocol='ldap')
+
+ _writeIstioNAP(name='tcp-default', server=server, listen_address=listen_address,
+ listen_port=admin_server_port, protocol='t3')
+
+ _writeIstioNAP(name='http-default', server=server, listen_address=listen_address,
+ listen_port=admin_server_port, protocol='http')
+
+ _writeIstioNAP(name='tcp-snmp', server=server, listen_address=listen_address,
+ listen_port=admin_server_port, protocol='snmp')
+
+ _writeIstioNAP(name='tcp-cbt', server=server, listen_address=listen_address,
+ listen_port=admin_server_port, protocol='CLUSTER-BROADCAST')
+
+ _writeIstioNAP(name='tcp-iiop', server=server, listen_address=listen_address,
+ listen_port=admin_server_port, protocol='iiop')
+
+ ssl = getSSLOrNone(server)
+ ssl_listen_port = None
+ model = env.getModel()
+ if ssl is not None and 'Enabled' in ssl and ssl['Enabled'] == 'true':
+ ssl_listen_port = ssl['ListenPort']
+ elif ssl is None and isSecureModeEnabledForDomain(model['topology']):
+ ssl_listen_port = "7002"
+
+ if ssl_listen_port is not None:
+ _writeIstioNAP(name='https-secure', server=server, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='https', http_enabled="true")
+
+ _writeIstioNAP(name='tls-ldaps', server=server, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='ldaps')
+
+ _writeIstioNAP(name='tls-default', server=server, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='t3s')
+
+ _writeIstioNAP(name='tls-cbts', server=server, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='CLUSTER-BROADCAST-SECURE')
+
+ _writeIstioNAP(name='tls-iiops', server=server, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='iiops')
+
+ if isAdministrationPortEnabledForServer(server, model['topology']):
+ _writeIstioNAP(name='https-admin', server=server, listen_address=listen_address,
+ listen_port=getAdministrationPort(server, model['topology']), protocol='https', http_enabled="true")
+
+
+def customizeManagedIstioNetworkAccessPoint(template, listen_address):
+ istio_enabled = env.getEnvOrDef("ISTIO_ENABLED", "false")
+ if istio_enabled == 'false':
+ return
+ istio_readiness_port = env.getEnvOrDef("ISTIO_READINESS_PORT", None)
+ if istio_readiness_port is None:
+ return
+ listen_port = template['ListenPort']
+ # readiness probe
+ _writeIstioNAP(name='http-probe', server=template, listen_address=listen_address,
+ listen_port=istio_readiness_port, protocol='http', http_enabled="true")
+
+ # Generate NAP for each protocols
+ _writeIstioNAP(name='tcp-ldap', server=template, listen_address=listen_address,
+ listen_port=listen_port, protocol='ldap')
+
+ _writeIstioNAP(name='tcp-default', server=template, listen_address=listen_address,
+ listen_port=listen_port, protocol='t3')
+
+ _writeIstioNAP(name='http-default', server=template, listen_address=listen_address,
+ listen_port=listen_port, protocol='http')
+
+ _writeIstioNAP(name='tcp-snmp', server=template, listen_address=listen_address,
+ listen_port=listen_port, protocol='snmp')
+
+ _writeIstioNAP(name='tcp-cbt', server=template, listen_address=listen_address,
+ listen_port=listen_port, protocol='CLUSTER-BROADCAST')
+
+ _writeIstioNAP(name='tcp-iiop', server=template, listen_address=listen_address,
+ listen_port=listen_port, protocol='iiop')
+
+ ssl = getSSLOrNone(template)
+ ssl_listen_port = None
+ model = env.getModel()
+ if ssl is not None and 'Enabled' in ssl and ssl['Enabled'] == 'true':
+ ssl_listen_port = ssl['ListenPort']
+ elif ssl is None and isSecureModeEnabledForDomain(model['topology']):
+ ssl_listen_port = "7002"
+
+ if ssl_listen_port is not None:
+ _writeIstioNAP(name='https-secure', server=template, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='https', http_enabled="true")
+
+ _writeIstioNAP(name='tls-ldaps', server=template, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='ldaps')
+
+ _writeIstioNAP(name='tls-default', server=template, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='t3s')
+
+ _writeIstioNAP(name='tls-cbts', server=template, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='CLUSTER-BROADCAST-SECURE')
+
+ _writeIstioNAP(name='tls-iiops', server=template, listen_address=listen_address,
+ listen_port=ssl_listen_port, protocol='iiops')
+
+
+def customizeNetworkAccessPoints(server, listen_address):
+ if 'NetworkAccessPoint' not in server:
+ return
+
+ naps = server['NetworkAccessPoint']
+ nap_names = naps.keys()
+ for nap_name in nap_names:
+ nap = naps[nap_name]
+ customizeNetworkAccessPoint(nap, listen_address)
+
+
+def customizeNetworkAccessPoint(nap, listen_address):
+ istio_enabled = env.getEnvOrDef("ISTIO_ENABLED", "false")
+
+ if 'ListenAddress' in nap:
+ original_listen_address = nap['ListenAddress']
+ if len(original_listen_address) > 0:
+ if istio_enabled == 'true':
+ nap['ListenAddress'] = '127.0.0.1'
+ else:
+ nap['ListenAddress'] = listen_address
+
+
+def setServerListenAddress(serverOrTemplate, listen_address):
+ serverOrTemplate['ListenAddress'] = listen_address
+
+
+def customizeDefaultFileStore(server):
+ data_dir = env.getDataHome()
+ if data_dir is None or len(data_dir) == 0:
+ # do not override if dataHome not specified or empty ("")
+ return
+
+ if 'DefaultFileStore' not in server:
+ server['DefaultFileStore'] = {}
+
+ server['DefaultFileStore']['Directory'] = data_dir
+
+
+def customizeAccessLog(name, server):
+ # do not customize if LOG_HOME is not set
+ logs_dir = env.getDomainLogHome()
+ if logs_dir is None or len(logs_dir) == 0:
+ return
+
+ # customize only if ACCESS_LOG_IN_LOG_HOME is 'true'
+ if env.isAccessLogInLogHome():
+ if 'WebServer' not in server:
+ server['WebServer'] = {}
+
+ web_server = server['WebServer']
+ if 'WebServerLog' not in web_server:
+ web_server['WebServerLog'] = {}
+
+ web_server_log = web_server['WebServerLog']
+ if 'FileName' not in web_server_log:
+ web_server_log['FileName'] = {}
+
+ web_server_log['FileName'] = logs_dir + "/" + name + "_access.log"
+
+
+def getLogOrNone(config):
+ if 'Log' not in config:
+ return None
+
+ return config['Log']
+
+
+def getClusterNameOrNone(serverOrTemplate):
+ if 'Cluster' not in serverOrTemplate:
+ return None
+
+ return serverOrTemplate['Cluster']
+
+
+def getClusterOrNone(topology, name):
+ if 'Cluster' not in topology:
+ return
+
+ clusters = topology['Cluster']
+
+ if name in clusters:
+ return clusters[name]
+
+ return None
+
+
+def getDynamicServerOrNone(cluster):
+ if 'DynamicServers' not in cluster:
+ return None
+
+ return cluster['DynamicServers']
+
+
+def getDynamicServerPropertyOrNone(dynamicServer, name):
+ if name not in dynamicServer:
+ return None
+
+ return dynamicServer[name]
+
+
+def getSecretManager():
+ return secret_manager
diff --git a/operator/src/main/resources/scripts/startNodeManager.sh b/operator/src/main/resources/scripts/startNodeManager.sh
index bb7f547fedf..a39937c3002 100644
--- a/operator/src/main/resources/scripts/startNodeManager.sh
+++ b/operator/src/main/resources/scripts/startNodeManager.sh
@@ -241,13 +241,20 @@ if [ ! "${SERVER_NAME}" = "introspector" ]; then
[ ! $? -eq 0 ] && trace SEVERE "Could not remove stale file '$wl_state_file'." && exit 1
fi
+ if [ ${DOMAIN_SOURCE_TYPE} == "FromModel" ]; then
+ # Domain source type is 'FromModel' (MII) then disable Situation config override for WebLogic.
+ failBootOnErrorOption=""
+ else
+ failBootOnErrorOption="-Dweblogic.SituationalConfig.failBootOnError=${FAIL_BOOT_ON_SITUATIONAL_CONFIG_ERROR}"
+ fi
+
cat < ${wl_props_file}
# Server startup properties
AutoRestart=true
RestartMax=2
RestartInterval=3600
NMHostName=${SERVICE_NAME}
-Arguments=${USER_MEM_ARGS} -Dweblogic.SituationalConfig.failBootOnError=${FAIL_BOOT_ON_SITUATIONAL_CONFIG_ERROR} ${serverOutOption} ${JAVA_OPTIONS}
+Arguments=${USER_MEM_ARGS} ${failBootOnErrorOption} ${serverOutOption} ${JAVA_OPTIONS}
EOF
diff --git a/operator/src/main/resources/scripts/startServer.sh b/operator/src/main/resources/scripts/startServer.sh
index cf1b54819b6..e4925005c3b 100755
--- a/operator/src/main/resources/scripts/startServer.sh
+++ b/operator/src/main/resources/scripts/startServer.sh
@@ -102,8 +102,12 @@ function startWLS() {
FAIL_BOOT_ON_SITUATIONAL_CONFIG_ERROR=${FAIL_BOOT_ON_SITUATIONAL_CONFIG_ERROR:-true}
SERVER_OUT_MONITOR_INTERVAL=${SERVER_OUT_MONITOR_INTERVAL:-3}
- if [ ${FAIL_BOOT_ON_SITUATIONAL_CONFIG_ERROR} == 'true' ] ; then
- ${SCRIPTPATH}/monitorLog.sh ${SERVER_OUT_FILE} ${SERVER_OUT_MONITOR_INTERVAL} &
+ if [ ${DOMAIN_SOURCE_TYPE} != "FromModel" ]; then
+ # If Domain source type is not FromModel (MII) then monitor server logs for invalid
+ # Situational config override files.
+ if [ ${FAIL_BOOT_ON_SITUATIONAL_CONFIG_ERROR} == 'true' ] ; then
+ ${SCRIPTPATH}/monitorLog.sh ${SERVER_OUT_FILE} ${SERVER_OUT_MONITOR_INTERVAL} &
+ fi
fi
}
@@ -174,7 +178,7 @@ traceDirs before DOMAIN_HOME LOG_HOME DATA_HOME
traceTiming "POD '${SERVICE_NAME}' MII UNZIP START"
-if [ -f /weblogic-operator/introspector/domainzip.secure ]; then
+if [ ${DOMAIN_SOURCE_TYPE} == "FromModel" ]; then
prepareMIIServer
if [ $? -ne 0 ] ; then
trace SEVERE "Domain Source Type is FromModel, unable to start the server, check other error messages in the log"
@@ -281,10 +285,13 @@ createFolder ${DOMAIN_HOME}/servers/${SERVER_NAME}/security
copyIfChanged /weblogic-operator/introspector/boot.properties \
${DOMAIN_HOME}/servers/${SERVER_NAME}/security/boot.properties
-copySitCfgWhileBooting /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig 'Sit-Cfg-CFG--'
-copySitCfgWhileBooting /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/jms 'Sit-Cfg-JMS--'
-copySitCfgWhileBooting /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/jdbc 'Sit-Cfg-JDBC--'
-copySitCfgWhileBooting /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/diagnostics 'Sit-Cfg-WLDF--'
+if [ ${DOMAIN_SOURCE_TYPE} != "FromModel" ]; then
+ trace "Copying situational configuration files from operator cm to ${DOMAIN_HOME}/optconfig directory"
+ copySitCfgWhileBooting /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig 'Sit-Cfg-CFG--'
+ copySitCfgWhileBooting /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/jms 'Sit-Cfg-JMS--'
+ copySitCfgWhileBooting /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/jdbc 'Sit-Cfg-JDBC--'
+ copySitCfgWhileBooting /weblogic-operator/introspector ${DOMAIN_HOME}/optconfig/diagnostics 'Sit-Cfg-WLDF--'
+fi
#
# Start WLS
diff --git a/operator/src/test/python/__init__.py b/operator/src/test/python/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/operator/src/test/python/test_wdt_mii_filter.py b/operator/src/test/python/test_wdt_mii_filter.py
new file mode 100644
index 00000000000..c376dbc2a9f
--- /dev/null
+++ b/operator/src/test/python/test_wdt_mii_filter.py
@@ -0,0 +1,257 @@
+import ast
+import os
+import unittest
+#import yaml
+
+import model_wdt_mii_filter
+
+
+class WdtUpdateFilterCase(unittest.TestCase):
+
+ ISTIO_NAP_NAMES = ['tcp-cbt', 'tcp-ldap', 'tcp-iiop', 'tcp-snmp', 'http-probe', 'http-default', 'tcp-default']
+
+ def setUp(self):
+ self.initialize_environment_variables()
+
+
+ def initialize_environment_variables(self):
+ os.environ['DOMAIN_UID'] = 'sample-domain1'
+ os.environ['DOMAIN_HOME'] = '/u01/domains/sample-domain1'
+ os.environ['LOG_HOME'] = '/u01/logs/sample-domain1'
+ os.environ[
+ 'CREDENTIALS_SECRET_NAME'] = 'sample-domain1-weblogic-credentials'
+ os.environ['DOMAIN_SOURCE_TYPE'] = 'FromModel'
+ os.environ['DATA_HOME'] = '/u01/datahome'
+
+ def initialize_istio_naps(self):
+ istio_naps = {}
+
+ self.add_istio_nap_to_dict(istio_naps, name='http-probe', protocol='http', http_enabled="true")
+ self.add_istio_nap_to_dict(istio_naps, name='tcp-ldap', protocol='ldap', http_enabled="false")
+
+
+ def add_istio_nap_to_dict(self, istio_naps, name, protocol, http_enabled):
+ if name in istio_naps:
+ return
+
+ istio_naps.setdefault(name, {})
+ listen_address=self.env.toDNS1123Legal(self.env.getDomainUID() + "-" + name)
+ nap = istio_naps[name]
+ nap['Protocol'] = protocol
+ nap['ListenAddres'] = '127.0.0.1'
+ nap['PublicAddress'] = '%s.%s' % (listen_address, self.env.getEnvOrDef("ISTIO_POD_NAMESPACE", "default"))
+ nap['ListenPort'] = self.env.getEnvOrDef("ISTIO_READINESS_PORT", None)
+ nap['HttpEnabledForThisProtocol'] = http_enabled
+ nap['TunnelingEnabled'] = 'false'
+ nap['OutboundEnabled'] = 'false'
+ nap['Enabled'] = 'true'
+ nap['TwoWaySslEnabled'] = 'false'
+ nap['ClientCertificateEnforced'] = 'false'
+
+ def getModel(self):
+ # Load model as dictionary
+ file = open(r'../resources/model.dynamic_cluster_dict.txt')
+ contents = file.read()
+ model = ast.literal_eval(contents)
+ file.close()
+
+ # Setup mock environment
+ mock_env= MockOfflineWlstEnv()
+ mock_env.open(model)
+ model_wdt_mii_filter.env = mock_env
+
+ return model
+
+ def getStaticModel(self):
+ # Load model as dictionary
+ file = open(r'../resources/model.static_cluster_dict.txt')
+ contents = file.read()
+ model = ast.literal_eval(contents)
+ file.close()
+
+ # Setup mock environment
+ mock_env= MockOfflineWlstEnv()
+ mock_env.open(model)
+ model_wdt_mii_filter.env = mock_env
+
+ return model
+
+ def writeModelAsDict(self, model, file_path):
+ f = open(file_path,"w")
+ f.write( str(model) )
+ f.close()
+
+ def getServerTemplate(self, model):
+ template_name = 'cluster-1-template'
+ topology = model['topology']
+ server_template = topology['ServerTemplate'][template_name]
+ return server_template
+
+
+ def test_get_server_name_prefix(self):
+ model = self.getModel()
+
+ server_template = self.getServerTemplate(model)
+ server_name_prefix = model_wdt_mii_filter.getServerNamePrefix(model['topology'], server_template)
+ self.assertEqual('managed-server', server_name_prefix, "Expected server name prefix to be \'managed-server\'")
+
+
+ def test_customize_admin_server_static_cluster(self):
+ model = self.getStaticModel()
+
+ server_name = 'admin-server'
+ server = model['topology']['Server'][server_name]
+ model_wdt_mii_filter.customizeServer(server, server_name)
+ listen_address = server['ListenAddress']
+ self.assertEqual('sample-domain1-admin-server', listen_address, "Expected listen address to be \'sample-domain1-admin-server\'")
+
+ def test_customize_log_in_server_template(self):
+ model = self.getModel()
+
+ server_template = self.getServerTemplate(model)
+ model_wdt_mii_filter.customizeLog("managed-server${id}", server_template)
+ template_log_filename = server_template['Log']['FileName']
+ self.assertEqual('/u01/logs/sample-domain1/managed-server${id}.log', template_log_filename, "Expected listen address to be \'/u01/logs/sample-domain1/managed-server${id}.log\'")
+
+ def test_customize_access_log_in_server_template(self):
+ model = self.getModel()
+
+ server_template = self.getServerTemplate(model)
+ model_wdt_mii_filter.customizeAccessLog("managed-server${id}", server_template)
+ template_access_log = server_template['WebServer']['WebServerLog']['FileName']
+ self.assertEqual('/u01/logs/sample-domain1/managed-server${id}_access.log', template_access_log, "Expected listen address to be \'/u01/logs/sample-domain1/managed-server${id}.log\'")
+
+
+ def test_customize_default_filestore_in_server_template(self):
+ model = self.getModel()
+
+ server_template = self.getServerTemplate(model)
+ model_wdt_mii_filter.customizeDefaultFileStore(server_template)
+ default_filestore = server_template['DefaultFileStore']['Directory']
+ self.assertEqual('/u01/datahome', default_filestore, "Expected default file store directory to be \'/u01/datahome\'")
+
+
+ def test_customize_network_access_points_in_server_template(self):
+ model = self.getModel()
+
+ server_template = self.getServerTemplate(model)
+ model_wdt_mii_filter.customizeNetworkAccessPoints(server_template, 'sample-domain1-managed-server${id}')
+ nap_listen_address = model['topology']['ServerTemplate']['cluster-1-template']['NetworkAccessPoint']['T3Channel']['ListenAddress']
+ self.assertEqual('sample-domain1-managed-server${id}', nap_listen_address, "Expected nap listen address to be \'sample-domain1-managed-server${id}\'")
+
+ def test_customize_istio_enabled_network_access_points_in_server_template(self):
+ try:
+ os.environ['ISTIO_ENABLED'] = 'true'
+ model = self.getModel()
+
+ server_template = self.getServerTemplate(model)
+ model_wdt_mii_filter.customizeNetworkAccessPoints(server_template, 'sample-domain1-managed-server${id}')
+ nap_listen_address = model['topology']['ServerTemplate']['cluster-1-template']['NetworkAccessPoint']['T3Channel']['ListenAddress']
+ self.assertEqual('127.0.0.1', nap_listen_address, "Expected nap listen address to be \'127.0.0.1\'")
+ finally:
+ del os.environ['ISTIO_ENABLED']
+
+ def test_customize_managed_istio_network_access_point_in_server_template(self):
+ try:
+ os.environ['ISTIO_ENABLED'] = 'true'
+ os.environ['ISTIO_READINESS_PORT'] = '8088'
+ model = self.getModel()
+
+ template_name = 'cluster-1-template'
+ server_template = self.getServerTemplate(model)
+ model_wdt_mii_filter.customizeManagedIstioNetworkAccessPoint(server_template, 'sample-domain1-managed-server${id}')
+ naps = server_template.get('NetworkAccessPoint')
+ self.assertGreater(len(naps), 1)
+ names = list(naps.keys())
+ names.remove('T3Channel')
+ for name in names:
+ self.assertIn(name, WdtUpdateFilterCase.ISTIO_NAP_NAMES)
+ finally:
+ del os.environ['ISTIO_ENABLED']
+ del os.environ['ISTIO_READINESS_PORT']
+
+
+ def test_customizeServerTemplates(self):
+ model = self.getModel()
+
+ model_wdt_mii_filter.customizeServerTemplates(model)
+ listen_address = model['topology']['ServerTemplate']['cluster-1-template']['ListenAddress']
+ self.assertEqual('sample-domain1-managed-server${id}', listen_address, "Expected listen address to be \'sample-domain1-managed-server${id}\'")
+
+ def test_customizeServerTemplate(self):
+ model = self.getModel()
+ topology = model['topology']
+ template_name = 'cluster-1-template'
+
+ serverTemplate = topology['ServerTemplate'][template_name]
+ model_wdt_mii_filter.customizeServerTemplate(topology, serverTemplate)
+
+ # verify custom log in server template
+ template_log_filename = serverTemplate['Log']['FileName']
+ self.assertEqual('/u01/logs/sample-domain1/managed-server${id}.log', template_log_filename, "Expected listen address to be \'/u01/logs/sample-domain1/managed-server${id}.log\'")
+
+ # verify custom access log in server template
+ template_access_log = serverTemplate['WebServer']['WebServerLog']['FileName']
+ self.assertEqual('/u01/logs/sample-domain1/managed-server${id}_access.log', template_access_log, "Expected listen address to be \'/u01/logs/sample-domain1/managed-server${id}.log\'")
+
+ # verify listen address in server template
+ listen_address = model['topology']['ServerTemplate'][template_name]['ListenAddress']
+ self.assertEqual('sample-domain1-managed-server${id}', listen_address, "Expected listen address to be \'sample-domain1-managed-server${id}\'")
+
+ def test_getClusterOrNone_returns_none(self):
+ model = self.getModel()
+ cluster = model_wdt_mii_filter.getClusterOrNone(model, "cluster-2")
+ self.assertIsNone(cluster, "Did not expect to find cluster named \'cluster-2\'")
+
+ def test_customize_node_manager_creds(self):
+ model = self.getModel()
+ model_wdt_mii_filter.initSecretManager(model_wdt_mii_filter.getOfflineWlstEnv())
+ model_wdt_mii_filter.customizeNodeManagerCreds(model['topology'])
+ self.assertEqual(MockOfflineWlstEnv.WLS_CRED_USERNAME, model['topology']['SecurityConfiguration']['NodeManagerUsername'], "Expected node manager username to be \'" + MockOfflineWlstEnv.WLS_CRED_USERNAME + "\'")
+ self.assertEqual(MockOfflineWlstEnv.WLS_CRED_PASSWORD, model['topology']['SecurityConfiguration']['NodeManagerPasswordEncrypted'], "Expected node manager password to be \'" + MockOfflineWlstEnv.WLS_CRED_PASSWORD + "\'")
+
+ def test_customizeDomainLogPath(self):
+ model = self.getModel()
+ model_wdt_mii_filter.customizeDomainLogPath(model['topology'])
+ self.assertEqual('/u01/logs/sample-domain1/sample-domain1.log', model['topology']['Log']['FileName'], "Expected domain log file name to be \'/u01/logs/sample-domain1/sample-domain1.log\'")
+
+ def test_customizeLog_whenNoNameProvided(self):
+ model = self.getModel()
+ model_wdt_mii_filter.customizeLog(None, model['topology'])
+ self.assertNotIn('Log', model['topology'], "Did not expect \'Log\' to be configured")
+
+ def test_customizeCustomFileStores(self):
+ model = self.getModel()
+ model_wdt_mii_filter.customizeCustomFileStores(model)
+ self.assertEqual('/u01/datahome', model['resources']['FileStore']['FileStore-0']['Directory'], "Expected custom filestore directory \'/u01/datahome\'")
+
+ def test_customizeServers(self):
+ model = self.getModel()
+ model_wdt_mii_filter.customizeServers(model)
+ self.assertEqual('sample-domain1-admin-server', model['topology']['Server']['admin-server']['ListenAddress'], "Expected server listen address to be \'sample-domain1-admin-server\'")
+
+ def test_readDomainNameFromTopologyYaml(self):
+ model = self.getModel()
+ model_wdt_mii_filter.env.readDomainNameFromTopologyYaml('../resources/topology.yaml')
+ domain_name = model_wdt_mii_filter.env.getDomainName()
+ self.assertEqual('wls-domain1', domain_name, "Expected domain name to be \'wls-domain1\'")
+
+class MockOfflineWlstEnv(model_wdt_mii_filter.OfflineWlstEnv):
+
+ WLS_CRED_USERNAME = 'weblogic'
+ WLS_CRED_PASSWORD = 'password'
+
+ def __init__(self):
+ model_wdt_mii_filter.OfflineWlstEnv.__init__(self)
+
+ def encrypt(self, cleartext):
+ return cleartext
+
+ def readFile(self, path):
+ if path.endswith('username'):
+ return self.WLS_CRED_USERNAME
+
+ return self.WLS_CRED_PASSWORD
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/operator/src/test/resources/model.dynamic_cluster_dict.txt b/operator/src/test/resources/model.dynamic_cluster_dict.txt
new file mode 100644
index 00000000000..1937c634979
--- /dev/null
+++ b/operator/src/test/resources/model.dynamic_cluster_dict.txt
@@ -0,0 +1 @@
+{'appDeployments': {'Application': {'myapp': {'SourcePath': 'wlsdeploy/applications/myapp-v1', 'ModuleType': 'ear', 'Target': 'cluster-1'}}}, 'domainInfo': {'AdminUserName': 'weblogic', 'ServerStartMode': 'dev', 'AdminPassword': 'welcome1'}, 'resources': {'FileStore': {'FileStore-0': {'Directory': '/u01/oracle/customFileStore/', 'Target': 'cluster-1'}}}, 'topology': {'Cluster': {'cluster-1': {'DynamicServers': {'MinDynamicClusterSize': '0', 'CalculatedListenPorts': False, 'MaxDynamicClusterSize': '5', 'ServerNamePrefix': 'managed-server', 'DynamicClusterSize': '5', 'ServerTemplate': 'cluster-1-template'}}}, 'AdminServerName': 'admin-server', 'Server': {'admin-server': {'ListenPort': 7001}}, 'ServerTemplate': {'cluster-1-template': {'NetworkAccessPoint': {'T3Channel': {'PublicAddress': 'admin-server-public-service', 'PublicPort': 9003, 'ListenPort': 8003, 'ListenAddress': 'admin-server-service'}}, 'Cluster': 'cluster-1', 'ListenPort': 8001}}, 'Name': 'sample-domain1'}}
\ No newline at end of file
diff --git a/operator/src/test/resources/model.static_cluster_dict.txt b/operator/src/test/resources/model.static_cluster_dict.txt
new file mode 100644
index 00000000000..037efecac23
--- /dev/null
+++ b/operator/src/test/resources/model.static_cluster_dict.txt
@@ -0,0 +1 @@
+{'appDeployments': {'Application': {'myapp': {'SourcePath': 'wlsdeploy/applications/myapp-v1', 'ModuleType': 'ear', 'Target': 'cluster-2'}}}, 'domainInfo': {'AdminUserName': 'weblogic', 'ServerStartMode': 'dev', 'AdminPassword': 'welcome1'}, 'resources': {'FileStore': {'FileStore-0': {'Directory': '/u01/oracle/customFileStore/', 'Target': 'cluster-2'}}}, 'topology': {'Cluster': {'cluster-2': None}, 'AdminServerName': 'admin-server', 'Name': 'sample-domain1', 'Server': {'config-cluster-server1': {'Cluster': 'cluster-2', 'ListenPort': '8001'}, 'config-cluster-server2': {'Cluster': 'cluster-2', 'ListenPort': '8001'}, 'standalone-managed': {'ListenPort': '8001'}, 'admin-server': {'ListenPort': 7001}}}}
\ No newline at end of file
diff --git a/operator/src/test/resources/topology.yaml b/operator/src/test/resources/topology.yaml
new file mode 100644
index 00000000000..5cfa30c41d3
--- /dev/null
+++ b/operator/src/test/resources/topology.yaml
@@ -0,0 +1,24 @@
+domainValid: true
+domain:
+ name: "wls-domain1"
+ adminServerName: "admin-server"
+ configuredClusters:
+ - name: "cluster-1"
+ dynamicServersConfig:
+ name: "NO_NAME_0"
+ serverTemplateName: "cluster-1-template"
+ calculatedListenPorts: 0
+ serverNamePrefix: "managed-server"
+ dynamicClusterSize: 5
+ maxDynamicClusterSize: 5
+ minDynamicClusterSize: 1
+ serverTemplates:
+ - name: "cluster-1-template"
+ listenPort: 8001
+ listenAddress: "mii-dynamic-update-cluster-1-template"
+ clusterName: "cluster-1"
+ servers:
+ - name: "admin-server"
+ listenPort: 7001
+ listenAddress: "mii-dynamic-update-admin-server"
+