From 5dac86eab691d1da0dae369e7010532222e85f69 Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Wed, 1 Sep 2021 17:07:36 +0000 Subject: [PATCH 1/9] Update http-probe to bind to server ip --- .../src/main/resources/scripts/introspectDomain.py | 11 +++++++++-- .../main/resources/scripts/model_wdt_mii_filter.py | 14 ++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/operator/src/main/resources/scripts/introspectDomain.py b/operator/src/main/resources/scripts/introspectDomain.py index 1098a053014..22ed57c4478 100644 --- a/operator/src/main/resources/scripts/introspectDomain.py +++ b/operator/src/main/resources/scripts/introspectDomain.py @@ -1115,7 +1115,10 @@ def customizeNetworkAccessPoint(self, nap, listen_address): self.indent() self.writeln("" + nap_name + "") if istio_enabled == 'true': - self.writeListenAddress("force a replace", '127.0.0.1') + if nap_name == 'http-probe': + self.writeListenAddress("force a replace", listen_address) + else: + self.writeListenAddress("force a replace", '127.0.0.1') else: self.writeListenAddress("force a replace",listen_address) @@ -1155,7 +1158,11 @@ def _writeIstioNAP(self, name, server, listen_address, listen_port, protocol, ht self.writeln('%s' % name) self.writeln('%s' % (action, protocol)) - self.writeln('127.0.0.1' % action) + if name == 'http-probe': + self.writeln('%s.%s' % (action, listen_address, + self.env.getEnvOrDef("ISTIO_POD_NAMESPACE", "default"))) + else: + self.writeln('127.0.0.1' % action) self.writeln('%s.%s' % (action, listen_address, self.env.getEnvOrDef("ISTIO_POD_NAMESPACE", "default"))) self.writeln('%s' % (action, listen_port)) diff --git a/operator/src/main/resources/scripts/model_wdt_mii_filter.py b/operator/src/main/resources/scripts/model_wdt_mii_filter.py index 87326c94238..78ab4abec03 100644 --- a/operator/src/main/resources/scripts/model_wdt_mii_filter.py +++ b/operator/src/main/resources/scripts/model_wdt_mii_filter.py @@ -381,7 +381,10 @@ def _writeIstioNAP(name, server, listen_address, listen_port, protocol, http_ena nap = naps[name] nap['Protocol'] = protocol - nap['ListenAddress'] = '127.0.0.1' + if name == 'http-probe': + nap['ListenAddress'] = '%s.%s' % (listen_address, env.getEnvOrDef("ISTIO_POD_NAMESPACE", "default")) + else: + 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 @@ -527,17 +530,20 @@ def customizeNetworkAccessPoints(server, listen_address): nap_names = naps.keys() for nap_name in nap_names: nap = naps[nap_name] - customizeNetworkAccessPoint(nap, listen_address) + customizeNetworkAccessPoint(nap_name, nap, listen_address) -def customizeNetworkAccessPoint(nap, listen_address): +def customizeNetworkAccessPoint(nap_name, 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' + if nap_name == 'http-probe': + nap['ListenAddress'] = listen_address + else: + nap['ListenAddress'] = '127.0.0.1' else: nap['ListenAddress'] = listen_address From b12a2cf2a0cfa4bdfd10cccf1865b545e2d68efd Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Wed, 1 Sep 2021 19:46:55 +0000 Subject: [PATCH 2/9] Add readiness port NAP for both server pod ip and localhost --- operator/src/main/resources/scripts/introspectDomain.py | 6 ++++++ operator/src/main/resources/scripts/model_wdt_mii_filter.py | 6 ++++++ operator/src/test/python/test_wdt_mii_filter.py | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/operator/src/main/resources/scripts/introspectDomain.py b/operator/src/main/resources/scripts/introspectDomain.py index 22ed57c4478..8c937e8ed53 100644 --- a/operator/src/main/resources/scripts/introspectDomain.py +++ b/operator/src/main/resources/scripts/introspectDomain.py @@ -1217,6 +1217,9 @@ def customizeServerIstioNetworkAccessPoint(self, listen_address, server): self._writeIstioNAP(name='http-probe', server=server, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http', http_enabled="true") + self._writeIstioNAP(name='http-local-probe', server=server, listen_address=listen_address, + listen_port=istio_readiness_port, protocol='http', http_enabled="true") + # Generate NAP for each protocols self._writeIstioNAP(name='tcp-ldap', server=server, listen_address=listen_address, listen_port=admin_server_port, protocol='ldap') @@ -1271,6 +1274,9 @@ def customizeManagedIstioNetworkAccessPoint(self, listen_address, template): self._writeIstioNAP(name='http-probe', server=template, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http') + self._writeIstioNAP(name='http-local-probe', server=template, listen_address=listen_address, + listen_port=istio_readiness_port, protocol='http') + self._writeIstioNAP(name='tcp-default', server=template, listen_address=listen_address, listen_port=listen_port, protocol='t3', http_enabled='false') diff --git a/operator/src/main/resources/scripts/model_wdt_mii_filter.py b/operator/src/main/resources/scripts/model_wdt_mii_filter.py index 78ab4abec03..dbd5d764b84 100644 --- a/operator/src/main/resources/scripts/model_wdt_mii_filter.py +++ b/operator/src/main/resources/scripts/model_wdt_mii_filter.py @@ -410,6 +410,9 @@ def customizeServerIstioNetworkAccessPoint(server, listen_address): _writeIstioNAP(name='http-probe', server=server, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http', http_enabled="true") + _writeIstioNAP(name='http-local-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') @@ -476,6 +479,9 @@ def customizeManagedIstioNetworkAccessPoint(template, listen_address): _writeIstioNAP(name='http-probe', server=template, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http', http_enabled="true") + _writeIstioNAP(name='http-local-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') diff --git a/operator/src/test/python/test_wdt_mii_filter.py b/operator/src/test/python/test_wdt_mii_filter.py index ccca77c2355..1caedb75c60 100644 --- a/operator/src/test/python/test_wdt_mii_filter.py +++ b/operator/src/test/python/test_wdt_mii_filter.py @@ -8,7 +8,7 @@ class WdtUpdateFilterCase(unittest.TestCase): - ISTIO_NAP_NAMES = ['tcp-cbt', 'tcp-ldap', 'tcp-iiop', 'tcp-snmp', 'http-probe', 'http-default', 'tcp-default'] + ISTIO_NAP_NAMES = ['tcp-cbt', 'tcp-ldap', 'tcp-iiop', 'tcp-snmp', 'http-probe', 'http-local-probe', 'http-default', 'tcp-default'] def setUp(self): self.initialize_environment_variables() From 12c0b4610c6699944cb46f4689d2d36a59f87626 Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Wed, 15 Sep 2021 03:00:13 +0000 Subject: [PATCH 3/9] Create localhost binding NAPs --- .../resources/scripts/introspectDomain.py | 310 +++++++++++++++++- .../resources/scripts/model_wdt_mii_filter.py | 86 ++++- .../src/test/python/test_wdt_mii_filter.py | 59 +++- 3 files changed, 426 insertions(+), 29 deletions(-) diff --git a/operator/src/main/resources/scripts/introspectDomain.py b/operator/src/main/resources/scripts/introspectDomain.py index 8c937e8ed53..e4d225c09c9 100644 --- a/operator/src/main/resources/scripts/introspectDomain.py +++ b/operator/src/main/resources/scripts/introspectDomain.py @@ -99,6 +99,8 @@ from utils import * from weblogic.management.configuration import LegalHelper +ISTIO_NAP_NAMES = ['tcp-cbt', 'tcp-ldap', 'tcp-iiop', 'tcp-snmp', 'http-default', 'tcp-default', 'https-secure', 'tls-ldaps', 'tls-default', 'tls-cbts', 'tls-iiops', 'https-admin'] +WLS_LOCALHOST_IDENTIFIER = '-lh' class OfflineWlstEnv(object): @@ -751,7 +753,8 @@ def addNetworkAccessPoint(self, server, nap, 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-'): + if name.startswith('http-') or name.startswith('tcp-') or name.startswith('tls-') \ + or name.startswith('https-') or nameContainsLocalHostIdentifier(name): # skip istio ports already defined by WDT filtering for MII return http_protocol = [ 'http' ] @@ -1056,6 +1059,221 @@ def writeListenAddress(self, originalValue, newValue): repVerb="\"add\"" self.writeln("" + newValue + "") + def writeName(self, name): + self.writeln("" + name + "") + + def writeProtocol(self, protocol): + self.writeln("" + protocol + "") + + def writeListenPort(self, listen_port): + # offline WLST initializes int values to 0 + if listen_port > 0: + self.writeln("" + str(listen_port) + "") + + def writePublicAddress(self, public_address): + self.writeln("" + public_address + "") + + def writePublicPort(self, public_port): + # offline WLST initializes int values to 0 + if public_port > 0: + self.writeln("" + str(public_port) + "") + + def writeAcceptBacklog(self, accept_backlog): + # offline WLST initializes int values to 0 + if accept_backlog > 0: + self.writeln("" + str(accept_backlog) + "") + + def writeMaxBackoffBetweenFailures(self, maxBackoffBetweenFailures): + if maxBackoffBetweenFailures > 0: + self.writeln("" + str(maxBackoffBetweenFailures) + "") + + def writeLoginTimeoutMillis(self, loginTimeoutMillis): + # offline WLST initializes int values to 0 + if loginTimeoutMillis > 0: + self.writeln("" + str(loginTimeoutMillis) + "") + + def writeCompleteMessageTimeout(self, completeMessageTimeout): + # offline WLST initializes int values to 0 + if completeMessageTimeout > 0: + self.writeln("" + str(completeMessageTimeout) + "") + + def writeIdleConnectionTimeout(self, idleConnectionTimeout): + # offline WLST initializes int values to 0 + if idleConnectionTimeout > 0: + self.writeln("" + str(idleConnectionTimeout) + "") + + def writeConnectTimeout(self, connectTimeout): + # offline WLST initializes int values to 0 + if connectTimeout > 0: + self.writeln("" + str(connectTimeout) + "") + + def writeTunnelingClientPingSecs(self, tunnelingClientPingSecs): + # offline WLST initializes int values to 0 + if tunnelingClientPingSecs > 0: + self.writeln("" + str(tunnelingClientPingSecs) + "") + + def writeTunnelingClientTimeoutSecs(self, tunnelingClientTimeoutSecs): + # offline WLST initializes int values to 0 + if tunnelingClientTimeoutSecs > 0: + self.writeln("" + str(tunnelingClientTimeoutSecs) + "") + + def writeMaxMessageSize(self, maxMessageSize): + # offline WLST initializes int values to 0 + # Legal minimum max message size is 4096 + # Allow WLS to check legal range + if maxMessageSize > 0: + self.writeln("" + str(maxMessageSize) + "") + + def writeChannelWeight(self, channelWeight): + # default is 50 + if channelWeight != 50: + self.writeln("" + str(channelWeight) + "") + + def writeMaxConnectedClients(self, maxConnectedClients): + # default = java.lang.Integer.MAX_VALUE + if maxConnectedClients != 2147483647: + self.writeln("" + str(maxConnectedClients) + "") + + def writeEnabled(self, nap): + # default enabled = 'true' + if nap.isEnabled() == false: + enabled = 'false' + self.writeln("" + enabled + "") + + def writeTunnelingEnabled(self, nap): + # default tunnelingEnabled = 'false' + if nap.isTunnelingEnabled() == true: + tunnelingEnabled = 'true' + self.writeln("" + tunnelingEnabled + "") + + def writeOutboundEnabled(self, nap): + # default outboundEnabled = 'false' + if nap.isOutboundEnabled() == true: + outboundEnabled = 'true' + self.writeln("" + outboundEnabled + "") + + def writeUseFastSerialization(self, nap): + # default useFastSerialization = 'false' + if nap.getUseFastSerialization() == true: + useFastSerialization = 'true' + self.writeln("" + useFastSerialization + "") + + def writeHttpEnabledForThisProtocol(self, nap): + # default httpEnabledForThisProtocol = 'true' + if nap.isHttpEnabledForThisProtocol() == false: + httpEnabledForThisProtocol = 'false' + self.writeln("" + httpEnabledForThisProtocol + "") + + def writeTimeoutConnectionWithPendingResponses(self, nap): + # default timeoutConnectionWithPendingResponses = 'false' + if nap.getTimeoutConnectionWithPendingResponses() == true: + timeoutConnectionWithPendingResponses = 'true' + self.writeln("" + timeoutConnectionWithPendingResponses + "") + + def writeSDPEnabled(self, nap): + # default sdpEnabled = 'false' + if nap.isSDPEnabled() == true: + sdpEnabled = 'true' + self.writeln("" + sdpEnabled + "") + + def writeTwoWaySSLEnabled(self, nap): + # default twoWaySSLEnabled = 'false' + if nap.isTwoWaySSLEnabled() == true: + twoWaySSLEnabled = 'true' + self.writeln("" + twoWaySSLEnabled + "") + + def writeClientCertificateEnforced(self, nap): + # default clientCertificateEnforced = 'false' + if nap.isClientCertificateEnforced() == true: + clientCertificateEnforced = 'true' + self.writeln("" + clientCertificateEnforced + "") + + def writeChannelIdentityCustomized(self, nap): + # default channelIdentityCustomized = 'false' + if nap.isChannelIdentityCustomized() == true: + channelIdentityCustomized = 'true' + self.writeln("" + channelIdentityCustomized + "") + + def writeCustomPrivateKeyAlias(self, nap): + customPrivateKeyAlias = nap.getCustomPrivateKeyAlias() + if customPrivateKeyAlias is not None: + self.writeln("" + customPrivateKeyAlias + "") + + def writeCustomPrivateKeyPassPhraseEncrypted(self, nap): + customPriveKeyPassPhraseEncrypted = nap.getCustomPrivateKeyPassPhraseEncrypted() + if customPriveKeyPassPhraseEncrypted is not None and len(customPriveKeyPassPhraseEncrypted) > 0: + self.writeln("" + customPriveKeyPassPhraseEncrypted + "") + + def writeCustomIdentityKeyStoreType(self, nap): + customIdentityKeyStoreType = nap.getCustomIdentityKeyStoreType() + if customIdentityKeyStoreType is not None and len(customIdentityKeyStoreType) > 0: + self.writeln("" + customIdentityKeyStoreType + "") + + def writeCustomIdentityKeyStorePassPhraseEncrypted(self, nap): + customIdentityKeyStorePassPhraseEncrypted = nap.getCustomIdentityKeyStorePassPhraseEncrypted() + if customIdentityKeyStorePassPhraseEncrypted is not None and len(customIdentityKeyStorePassPhraseEncrypted) > 0: + self.writeln("" + customIdentityKeyStorePassPhraseEncrypted + "") + + def writeHostnameVerificationIgnored(self, nap): + # default hostnameVerificationIgnored = 'false' + if nap.isHostnameVerificationIgnored() == true: + hostnameVerificationIgnored = 'true' + self.writeln("" + hostnameVerificationIgnored + "") + + def writeHostnameVerifier(self, nap): + hostnameVerifier = nap.getHostnameVerifier() + if hostnameVerifier is not None and len(hostnameVerifier) > 0: + self.writeln("" + hostnameVerifier + "") + + def writeCiphersuites(self, nap): + ciphersuites = nap.getCiphersuites() + if ciphersuites is not None: + for cipher in ciphersuites: + self.writeln("" + cipher + "") + + def writeAllowUnencryptedNullCipher(self, nap): + # default allowUnencryptedNullCipher = 'false' + if nap.isAllowUnencryptedNullCipher() == true: + allowUnencryptedNullCipher = 'true' + self.writeln("" + allowUnencryptedNullCipher + "") + + def writeInboundCertificateValidation(self, nap): + inboundCertificateValidation = nap.getInboundCertificateValidation() + if inboundCertificateValidation is not None and len(inboundCertificateValidation) > 0: + self.writeln("" + inboundCertificateValidation + "") + + def writeOutboundCertificateValidation(self, nap): + outboundCertificateValidation = nap.getOutboundCertificateValidation() + if outboundCertificateValidation is not None and len(outboundCertificateValidation) > 0: + self.writeln("" + outboundCertificateValidation + "") + + def createNameForLocalHostNetworkAccessPoint(self, nap_name, nap_name_dict): + # NAP names can be a maximum of 15 characters in length + key = nap_name + idx = 1 + if len(nap_name) >= 10: + # Slice out the first 10 characters to use since there is a 15 character + # limit to NAP names + key = nap_name[:10] + if key not in nap_name_dict: + # Add the first nap name with index=1 into the Dictionary + nap_name_dict[key] = idx + else: + # Found a nap with the same first 10 characters so increment and + # save the index + idx = nap_name_dict[key] + 1 + nap_name_dict[key] = idx + + # zero fill to the left for single digit index (e.g. 01) + idx_str = str(idx) + if idx < 10: + idx_str = '0' + idx_str + + # NAP name of for localhost binding will be of the form 'xxxxxxxxxx-lh01' + return key + WLS_LOCALHOST_IDENTIFIER + idx_str + + + def customizeServer(self, server): name=server.getName() listen_address=self.env.toDNS1123Legal(self.env.getDomainUID() + "-" + name) @@ -1097,8 +1315,10 @@ def customizeServerTemplate(self, template): self.writeln("") def customizeNetworkAccessPoints(self, server, listen_address): + nap_name_dict = {} for nap in server.getNetworkAccessPoints(): self.customizeNetworkAccessPoint(nap,listen_address) + self.createLocalHostNetworkAccessPoint(nap, '127.0.0.1', listen_address, nap_name_dict) def customizeNetworkAccessPoint(self, nap, listen_address): # Don't bother 'add' a nap listen-address, only do a 'replace'. @@ -1110,21 +1330,86 @@ def customizeNetworkAccessPoint(self, nap, listen_address): istio_enabled = self.env.getEnvOrDef("ISTIO_ENABLED", "false") nap_name=nap.getName() + if nap_name in ISTIO_NAP_NAMES or nameContainsLocalHostIdentifier(nap_name): + # skip customizing internal channels that were generated + return + + # replace listen address to bind to server pod IP if not (nap.getListenAddress() is None) and len(nap.getListenAddress()) > 0: self.writeln("") self.indent() self.writeln("" + nap_name + "") - if istio_enabled == 'true': - if nap_name == 'http-probe': - self.writeListenAddress("force a replace", listen_address) - else: - self.writeListenAddress("force a replace", '127.0.0.1') - else: - self.writeListenAddress("force a replace",listen_address) - + self.writeListenAddress("force a replace",listen_address) self.undent() self.writeln("") + # Create copy of custom NAP for binding to localhost for handling k8s 'port-forward' + # feature and Istio versions < 1.10.x + def createLocalHostNetworkAccessPoint(self, nap, listen_address, public_listen_address, nap_name_dict): + # Don't bother 'add' a nap listen-address, only do a 'replace'. + # If we try 'add' this appears to mess up an attempt to + # 'add' PublicAddress/Port via custom sit-cfg. + # FWIW there's theoretically no need to 'add' or 'replace' when empty + # since the runtime default is the server listen-address. + + istio_enabled = self.env.getEnvOrDef("ISTIO_ENABLED", "false") + if istio_enabled == 'true': + nap_name=nap.getName() + if nap_name in ISTIO_NAP_NAMES or nameContainsLocalHostIdentifier(nap_name): + # skip creating ISTIO channels + return + + self.writeln('') + self.indent() + self.writeName(self.createNameForLocalHostNetworkAccessPoint(nap_name, nap_name_dict)) + self.writeGeneralNetworkAccessPointConfiguration(nap, listen_address, public_listen_address) + self.writeSecureNetworkAccessPointConfiguration(nap) + self.undent() + self.writeln("") + + def writeGeneralNetworkAccessPointConfiguration(self, nap, listen_address, public_listen_address): + self.writeProtocol(nap.getProtocol()) + self.writeListenAddress("", listen_address) + self.writeListenPort(nap.getListenPort()) + self.writePublicAddress(public_listen_address) + self.writePublicPort(nap.getPublicPort()) + self.writeEnabled(nap) + self.writeOutboundEnabled(nap) + self.writeAcceptBacklog(nap.getAcceptBacklog()) + self.writeMaxBackoffBetweenFailures(nap.getMaxBackoffBetweenFailures()) + self.writeHttpEnabledForThisProtocol(nap) + self.writeLoginTimeoutMillis(nap.getLoginTimeoutMillis()) + self.writeCompleteMessageTimeout(nap.getCompleteMessageTimeout()) + self.writeIdleConnectionTimeout(nap.getIdleConnectionTimeout()) + self.writeConnectTimeout(nap.getConnectTimeout()) + self.writeTimeoutConnectionWithPendingResponses(nap) + self.writeTunnelingEnabled(nap) + self.writeTunnelingClientPingSecs(nap.getTunnelingClientPingSecs()) + self.writeTunnelingClientTimeoutSecs(nap.getTunnelingClientTimeoutSecs()) + self.writeMaxMessageSize(nap.getMaxMessageSize()) + self.writeChannelWeight(nap.getChannelWeight()) + self.writeMaxConnectedClients(nap.getMaxConnectedClients()) + self.writeUseFastSerialization(nap) + self.writeSDPEnabled(nap) + + def writeSecureNetworkAccessPointConfiguration(self, nap): + protocol = nap.getProtocol() + if protocol.endswith('s') or protocol == 'admin': + self.writeTwoWaySSLEnabled(nap) + self.writeClientCertificateEnforced(nap) + self.writeChannelIdentityCustomized(nap) + self.writeCustomPrivateKeyAlias(nap) + self.writeCustomPrivateKeyPassPhraseEncrypted(nap) + self.writeCustomIdentityKeyStoreType(nap) + self.writeCustomIdentityKeyStorePassPhraseEncrypted(nap) + self.writeHostnameVerificationIgnored(nap) + self.writeHostnameVerifier(nap) + self.writeCiphersuites(nap) + self.writeAllowUnencryptedNullCipher(nap) + self.writeInboundCertificateValidation(nap) + self.writeOutboundCertificateValidation(nap) + + def _getNapConfigOverrideAction(self, svr, testname): replace_action = 'f:combine-mode="replace"' add_action = 'f:combine-mode="add"' @@ -1217,7 +1502,7 @@ def customizeServerIstioNetworkAccessPoint(self, listen_address, server): self._writeIstioNAP(name='http-probe', server=server, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http', http_enabled="true") - self._writeIstioNAP(name='http-local-probe', server=server, listen_address=listen_address, + self._writeIstioNAP(name=self.createNameForLocalHostNetworkAccessPoint('http-probe', {}), server=server, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http', http_enabled="true") # Generate NAP for each protocols @@ -1274,7 +1559,7 @@ def customizeManagedIstioNetworkAccessPoint(self, listen_address, template): self._writeIstioNAP(name='http-probe', server=template, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http') - self._writeIstioNAP(name='http-local-probe', server=template, listen_address=listen_address, + self._writeIstioNAP(name=self.createNameForLocalHostNetworkAccessPoint('http-probe', {}), server=template, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http') self._writeIstioNAP(name='tcp-default', server=template, listen_address=listen_address, @@ -1889,6 +2174,9 @@ def get_server_template_listening_ports_from_configxml(config_xml): return server_template_ssls, server_template_ports +def nameContainsLocalHostIdentifier(name): + return name.find(WLS_LOCALHOST_IDENTIFIER) > -1 + def main(env): try: # Needs to build the domain first diff --git a/operator/src/main/resources/scripts/model_wdt_mii_filter.py b/operator/src/main/resources/scripts/model_wdt_mii_filter.py index dbd5d764b84..1ac1e6c0da2 100644 --- a/operator/src/main/resources/scripts/model_wdt_mii_filter.py +++ b/operator/src/main/resources/scripts/model_wdt_mii_filter.py @@ -44,7 +44,7 @@ # configuration. # - +import copy import inspect import os import sys @@ -55,12 +55,20 @@ sys.path.append(tmp_scriptdir) env = None +ISTIO_NAP_NAMES = ['tcp-cbt', 'tcp-ldap', 'tcp-iiop', 'tcp-snmp', 'http-default', 'tcp-default', 'https-secure', 'tls-ldaps', 'tls-default', 'tls-cbts', 'tls-iiops', 'https-admin'] +WLS_LOCALHOST_IDENTIFIER = '-lh' + class OfflineWlstEnv(object): def open(self, model): self.model = model + + # Dictionary to track the count of naps that have names > 15 characters + # key = 10 char name, value = index count + #self.nap_name_dict = {} + # before doing anything, get each env var and verify it exists self.DOMAIN_UID = self.getEnv('DOMAIN_UID') @@ -370,7 +378,7 @@ def getSSLOrNone(server): return server['SSL'] -def _writeIstioNAP(name, server, listen_address, listen_port, protocol, http_enabled="true"): +def _writeIstioNAP(name, server, listen_address, listen_port, protocol, http_enabled="true", bind_to_localhost="true"): if 'NetworkAccessPoint' not in server: server['NetworkAccessPoint'] = {} @@ -381,10 +389,10 @@ def _writeIstioNAP(name, server, listen_address, listen_port, protocol, http_ena nap = naps[name] nap['Protocol'] = protocol - if name == 'http-probe': - nap['ListenAddress'] = '%s.%s' % (listen_address, env.getEnvOrDef("ISTIO_POD_NAMESPACE", "default")) - else: + if bind_to_localhost == 'true': nap['ListenAddress'] = '127.0.0.1' + else: + nap['ListenAddress'] = '%s.%s' % (listen_address, env.getEnvOrDef("ISTIO_POD_NAMESPACE", "default")) nap['PublicAddress'] = '%s.%s' % (listen_address, env.getEnvOrDef("ISTIO_POD_NAMESPACE", "default")) nap['ListenPort'] = listen_port nap['HttpEnabledForThisProtocol'] = http_enabled @@ -408,9 +416,11 @@ def customizeServerIstioNetworkAccessPoint(server, listen_address): # readiness probe _writeIstioNAP(name='http-probe', server=server, listen_address=listen_address, - listen_port=istio_readiness_port, protocol='http', http_enabled="true") + listen_port=istio_readiness_port, protocol='http', http_enabled="true", + bind_to_localhost="false") - _writeIstioNAP(name='http-local-probe', server=server, listen_address=listen_address, + # readiness probe NAP binding to localhost + _writeIstioNAP(name=createNameForLocalHostNetworkAccessPoint('http-probe', {}), server=server, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http', http_enabled="true") # Generate NAP for each protocols @@ -477,9 +487,11 @@ def customizeManagedIstioNetworkAccessPoint(template, listen_address): listen_port = 7001 # readiness probe _writeIstioNAP(name='http-probe', server=template, listen_address=listen_address, - listen_port=istio_readiness_port, protocol='http', http_enabled="true") + listen_port=istio_readiness_port, protocol='http', http_enabled="true", + bind_to_localhost="false") - _writeIstioNAP(name='http-local-probe', server=template, listen_address=listen_address, + # readiness probe NAP binding to localhost address for Istio versions < 1.10.x + _writeIstioNAP(name=createNameForLocalHostNetworkAccessPoint('http-probe', {}), server=template, listen_address=listen_address, listen_port=istio_readiness_port, protocol='http', http_enabled="true") # Generate NAP for each protocols @@ -534,25 +546,67 @@ def customizeNetworkAccessPoints(server, listen_address): naps = server['NetworkAccessPoint'] nap_names = naps.keys() + # Dictionary to track the count of naps that have names > 15 characters + # key = 10 char name, value = index count + nap_name_dict = {} for nap_name in nap_names: nap = naps[nap_name] customizeNetworkAccessPoint(nap_name, nap, listen_address) + createLocalHostNetworkAccessPoint(nap_name, nap, server, nap_name_dict) def customizeNetworkAccessPoint(nap_name, nap, listen_address): - istio_enabled = env.getEnvOrDef("ISTIO_ENABLED", "false") + if nap_name in ISTIO_NAP_NAMES or nameContainsLocalHostIdentifier(nap_name): + # skip creating ISTIO channels + return + # fix NAP listen address if 'ListenAddress' in nap: original_listen_address = nap['ListenAddress'] if len(original_listen_address) > 0: - if istio_enabled == 'true': - if nap_name == 'http-probe': - nap['ListenAddress'] = listen_address - else: - nap['ListenAddress'] = '127.0.0.1' - else: nap['ListenAddress'] = listen_address +# Create copy of custom NAP for binding to localhost for handling k8s 'port-forward' +# feature and Istio versions < 1.10.x +def createLocalHostNetworkAccessPoint(nap_name, nap, server, nap_name_dict): + istio_enabled = env.getEnvOrDef("ISTIO_ENABLED", "false") + if istio_enabled == 'true': + if nap_name in ISTIO_NAP_NAMES or nameContainsLocalHostIdentifier(nap_name): + # skip creating ISTIO channels + return + + wls_local_nap = copy.deepcopy(nap) + wls_local_nap['ListenAddress'] = '127.0.0.1' + local_nap_name = createNameForLocalHostNetworkAccessPoint(nap_name, nap_name_dict) + server['NetworkAccessPoint'][local_nap_name] = wls_local_nap + +def createNameForLocalHostNetworkAccessPoint(nap_name, nap_name_dict): + # NAP names can be a maximum of 15 characters in length + key = nap_name + idx = 1 + if len(nap_name) >= 10: + # Slice out the first 10 characters to use since there is a 15 character + # limit to NAP names + key = nap_name[:10] + if key not in nap_name_dict: + # Add the first nap name with index=1 into the Dictionary + nap_name_dict[key] = idx + else: + # Found a nap with the same first 10 characters so increment and + # save the index + idx = nap_name_dict[key] + 1 + nap_name_dict[key] = idx + + # zero fill to the left for single digit index (e.g. 01) + idx_str = str(idx) + if idx < 10: + idx_str = '0' + idx_str + + # NAP name of for localhost binding will be of the form 'xxxxxxxxxx-lh01' + return key + WLS_LOCALHOST_IDENTIFIER + idx_str + +def nameContainsLocalHostIdentifier(name): + return name.find(WLS_LOCALHOST_IDENTIFIER) > -1 def setServerListenAddress(serverOrTemplate, listen_address): serverOrTemplate['ListenAddress'] = listen_address diff --git a/operator/src/test/python/test_wdt_mii_filter.py b/operator/src/test/python/test_wdt_mii_filter.py index 1caedb75c60..103c9d8e06f 100644 --- a/operator/src/test/python/test_wdt_mii_filter.py +++ b/operator/src/test/python/test_wdt_mii_filter.py @@ -8,7 +8,7 @@ class WdtUpdateFilterCase(unittest.TestCase): - ISTIO_NAP_NAMES = ['tcp-cbt', 'tcp-ldap', 'tcp-iiop', 'tcp-snmp', 'http-probe', 'http-local-probe', 'http-default', 'tcp-default'] + ISTIO_NAP_NAMES = ['tcp-cbt', 'tcp-ldap', 'tcp-iiop', 'tcp-snmp', 'http-probe', 'http-probe' + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', 'http-default', 'tcp-default'] def setUp(self): self.initialize_environment_variables() @@ -147,7 +147,17 @@ def test_customize_istio_enabled_network_access_points_in_server_template(self): 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\'") + self.assertEqual('sample-domain1-managed-server${id}', nap_listen_address, "Expected nap listen address to be \'sample-domain1-managed-server${id}\'") + + # Assert LocalHost channel listen address is '127.0.0.1' + nap_local_host = model['topology']['ServerTemplate']['cluster-1-template']['NetworkAccessPoint']['T3Channel' + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01']['ListenAddress'] + self.assertEqual('127.0.0.1', nap_local_host, "Expected nap listen address to be \'127.0.0.1\'") + + # Verify we don't duplicate channels more than once + model_wdt_mii_filter.customizeNetworkAccessPoints(server_template, 'sample-domain1-managed-server${id}') + naps = server_template['NetworkAccessPoint'] + nap_names = naps.keys() + self.assertEqual(2, len(nap_names), "Expected only two NAPS") finally: del os.environ['ISTIO_ENABLED'] @@ -236,6 +246,51 @@ def test_readDomainNameFromTopologyYaml(self): domain_name = model_wdt_mii_filter.env.getDomainName() self.assertEqual('wls-domain1', domain_name, "Expected domain name to be \'wls-domain1\'") + def test_createNameForLocalHostNetworkAccessPoint(self): + model = self.getModel() + nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint('http-probe', {}) + self.assertEquals('http-probe' + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be http-probe" + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') + + def test_createNameForLocalHostNetworkAccessPoint_with_long_name(self): + nap_name_10_chars = 'abcdefghij' + nap_name_15_chars = nap_name_10_chars + 'klmno' + nap_name_20_chars = nap_name_15_chars + 'pqrst' + + model = self.getModel() + nap_name_dict = {} + nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_10_chars, nap_name_dict) + self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') + + nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_15_chars, nap_name_dict) + self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02', nap_name_copy, "Expected 15 character name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02') + + nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '03', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '03') + + def test_createNameForLocalHostNetworkAccessPoint_with_double_digit_idx(self): + nap_name_10_chars = 'abcdefghij' + nap_name_20_chars = nap_name_10_chars + 'klmnopqrst' + nap_name_dict = {} + + # 01 + nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') + + # 02 + nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') + + model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + # 10 + nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) + self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '10', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '10') + class MockOfflineWlstEnv(model_wdt_mii_filter.OfflineWlstEnv): WLS_CRED_USERNAME = 'weblogic' From 414413259253f115676c43518532f795a145a08b Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Fri, 17 Sep 2021 20:34:47 +0000 Subject: [PATCH 4/9] Update Istio support document for Istio network changes --- .../staging/content/userguide/istio/istio.md | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/documentation/staging/content/userguide/istio/istio.md b/documentation/staging/content/userguide/istio/istio.md index 14e43d4dcbd..00c758a8350 100644 --- a/documentation/staging/content/userguide/istio/istio.md +++ b/documentation/staging/content/userguide/istio/istio.md @@ -142,6 +142,39 @@ If the WebLogic administration port is enabled on the Administration Server: Additionally, when Istio support is enabled for a domain, the operator ensures that the Istio sidecar is not injected into the introspector job's pods. +#### Support for network changes in Istio v1.10 and later + +Prior to Istio release 1.10, the Istio Envoy proxy redirected all inbound traffic to the localhost +network interface. The network channels listed above, which the operator automatically added, +were bound to the localhost interface in order for WebLogic to receive the inbound traffic. +Starting with Istio 1.10, the networking behavior was changed in that the proxy no longer redirects +the traffic to the localhost interface, but instead forwards it to the network interface associated +to the pod's IP. In order to support Istio v1.10 and later, as well as pre-1.10 releases, the +operator will: + +* Add an additional WebLogic HTTP protocol network channel for the readiness probe that is bound to the localhost network interface. +* Add additional WebLogic network channels, bound to the localhost network interface, for each defined custom network channel. +* Continue to automatically add the network channels described above in [How Istio-enabled domains differ from regular domains](#how-istio-enabled-domains-differ-from-regular-domains) + +When adding additional WebLogic network channels for the readiness probe and any defined custom channels, +the name of the additional channel will be appended with '-lhNN', where NN represents +a two digit value for uniqueness. + +For example, the additional WebLogic HTTP protocol network channel for the readiness probe would be +defined as follows: + +|Name|Port|Listening address|Protocol|Exposed as a container port| +|----|----|----|--------|-----| +|`http-probe-lh01`|From configuration Istio `readinessPort` | `127.0.0.1` | `http`| No | + +As another example, for a custom WebLogic network channel defined as `T3Channel` with port `5556` +and protocol `t3`, the additional channel would be defined as follows: + +|Name|Port|Listening address|Protocol|Exposed as a container port| +|----|----|----|--------|-----| +|`T3Channel-lh01`| `5556` | `127.0.0.1` | `t3`| Yes | + +To learn more about changes to Istio networking beginning with Istio 1.10, see [Upcoming networking changes in Istio 1.10](https://istio.io/latest/blog/2021/upcoming-networking-changes//). ### Apply the Domain YAML file From 2beb22a6210179f4b1e2eadfc10f99b79072c1be Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Sat, 18 Sep 2021 19:51:35 +0000 Subject: [PATCH 5/9] Fix pull request analysis failure and enhanced nameContainsLocalHostIdentifier() method --- .../resources/scripts/model_wdt_mii_filter.py | 30 +++++++++-- .../src/test/python/test_wdt_mii_filter.py | 51 ++++++++++++++++--- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/operator/src/main/resources/scripts/model_wdt_mii_filter.py b/operator/src/main/resources/scripts/model_wdt_mii_filter.py index 1ac1e6c0da2..a6e5cfe65f0 100644 --- a/operator/src/main/resources/scripts/model_wdt_mii_filter.py +++ b/operator/src/main/resources/scripts/model_wdt_mii_filter.py @@ -549,10 +549,18 @@ def customizeNetworkAccessPoints(server, listen_address): # Dictionary to track the count of naps that have names > 15 characters # key = 10 char name, value = index count nap_name_dict = {} + # Dictionary of LocalHost NAP's created + local_nap_dict = {} for nap_name in nap_names: nap = naps[nap_name] customizeNetworkAccessPoint(nap_name, nap, listen_address) - createLocalHostNetworkAccessPoint(nap_name, nap, server, nap_name_dict) + createLocalHostNetworkAccessPoint(nap_name, nap, nap_name_dict, local_nap_dict) + + # Iterate through the Dictionary of cloned local NAP's and add to the NetworkAccesPoint + # list of the model + local_nap_names = local_nap_dict.keys() + for local_nap_name in local_nap_names: + server['NetworkAccessPoint'][local_nap_name] = local_nap_dict[local_nap_name] def customizeNetworkAccessPoint(nap_name, nap, listen_address): @@ -568,7 +576,7 @@ def customizeNetworkAccessPoint(nap_name, nap, listen_address): # Create copy of custom NAP for binding to localhost for handling k8s 'port-forward' # feature and Istio versions < 1.10.x -def createLocalHostNetworkAccessPoint(nap_name, nap, server, nap_name_dict): +def createLocalHostNetworkAccessPoint(nap_name, nap, nap_name_dict, local_nap_dict): istio_enabled = env.getEnvOrDef("ISTIO_ENABLED", "false") if istio_enabled == 'true': if nap_name in ISTIO_NAP_NAMES or nameContainsLocalHostIdentifier(nap_name): @@ -578,7 +586,7 @@ def createLocalHostNetworkAccessPoint(nap_name, nap, server, nap_name_dict): wls_local_nap = copy.deepcopy(nap) wls_local_nap['ListenAddress'] = '127.0.0.1' local_nap_name = createNameForLocalHostNetworkAccessPoint(nap_name, nap_name_dict) - server['NetworkAccessPoint'][local_nap_name] = wls_local_nap + local_nap_dict[local_nap_name] = wls_local_nap def createNameForLocalHostNetworkAccessPoint(nap_name, nap_name_dict): # NAP names can be a maximum of 15 characters in length @@ -606,7 +614,21 @@ def createNameForLocalHostNetworkAccessPoint(nap_name, nap_name_dict): return key + WLS_LOCALHOST_IDENTIFIER + idx_str def nameContainsLocalHostIdentifier(name): - return name.find(WLS_LOCALHOST_IDENTIFIER) > -1 + # look for '-lh' + identifierIdx = name.find(WLS_LOCALHOST_IDENTIFIER) + # check if there is a localhost identifier + if identifierIdx > -1: + endIdentifierIdx = identifierIdx + len(WLS_LOCALHOST_IDENTIFIER) + # get substring from localhost identifier to end + subStr = name[endIdentifierIdx:] + print subStr + # should be only 2 digits 'NN' from '-lhNN' format + if len(subStr) == 2: + # verify the last two chars are digits + if subStr.isdigit(): + return True + + return False def setServerListenAddress(serverOrTemplate, listen_address): serverOrTemplate['ListenAddress'] = listen_address diff --git a/operator/src/test/python/test_wdt_mii_filter.py b/operator/src/test/python/test_wdt_mii_filter.py index 103c9d8e06f..809f7d4590c 100644 --- a/operator/src/test/python/test_wdt_mii_filter.py +++ b/operator/src/test/python/test_wdt_mii_filter.py @@ -249,7 +249,7 @@ def test_readDomainNameFromTopologyYaml(self): def test_createNameForLocalHostNetworkAccessPoint(self): model = self.getModel() nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint('http-probe', {}) - self.assertEquals('http-probe' + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be http-probe" + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') + self.assertEqual('http-probe' + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be http-probe" + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') def test_createNameForLocalHostNetworkAccessPoint_with_long_name(self): nap_name_10_chars = 'abcdefghij' @@ -259,13 +259,13 @@ def test_createNameForLocalHostNetworkAccessPoint_with_long_name(self): model = self.getModel() nap_name_dict = {} nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_10_chars, nap_name_dict) - self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') + self.assertEqual(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_15_chars, nap_name_dict) - self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02', nap_name_copy, "Expected 15 character name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02') + self.assertEqual(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02', nap_name_copy, "Expected 15 character name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02') nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) - self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '03', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '03') + self.assertEqual(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '03', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '03') def test_createNameForLocalHostNetworkAccessPoint_with_double_digit_idx(self): nap_name_10_chars = 'abcdefghij' @@ -274,11 +274,11 @@ def test_createNameForLocalHostNetworkAccessPoint_with_double_digit_idx(self): # 01 nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) - self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') + self.assertEqual(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') # 02 nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) - self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') + self.assertEqual(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '02', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01') model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) @@ -289,7 +289,44 @@ def test_createNameForLocalHostNetworkAccessPoint_with_double_digit_idx(self): model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) # 10 nap_name_copy = model_wdt_mii_filter.createNameForLocalHostNetworkAccessPoint(nap_name_20_chars, nap_name_dict) - self.assertEquals(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '10', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '10') + self.assertEqual(nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '10', nap_name_copy, "Expected name to be " + nap_name_10_chars + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '10') + + def test_createLocalHostNetworkAccessPoint(self): + try: + os.environ['ISTIO_ENABLED'] = 'true' + model = self.getModel() + server_template = self.getServerTemplate(model) + naps = server_template['NetworkAccessPoint'] + + nap_name_dict = {} + local_nap_dict = {} + nap = naps['T3Channel'] + model_wdt_mii_filter.createLocalHostNetworkAccessPoint('T3Channel', + nap, nap_name_dict, local_nap_dict) + self.assertEqual(1, len(local_nap_dict), "Expected only one dictionary entry") + self.assertTrue(local_nap_dict.has_key('T3Channel' + + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01')) + nap = local_nap_dict['T3Channel' + + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01'] + self.assertEqual('127.0.0.1', nap['ListenAddress'], + "Expected ListenAddress to be '\127.0.0.1\'") + finally: + del os.environ['ISTIO_ENABLED'] + + def test_nameContainsLocalHostIdentifier(self): + channelName = 'abced' + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01' + self.assertTrue(model_wdt_mii_filter.nameContainsLocalHostIdentifier(channelName), + "Expected name to contain " + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER) + + def test_nameDoesNotContainsLocalHostIdentifier(self): + channelName = 'abcedefg-l01' + self.assertFalse(model_wdt_mii_filter.nameContainsLocalHostIdentifier(channelName), + "Expected name to not contain " + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER) + + def test_localHostIdentifierDoesNotContainDigits(self): + channelName = 'abced' + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + 'o1' + self.assertFalse(model_wdt_mii_filter.nameContainsLocalHostIdentifier(channelName), + "Expected name to not contain " + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER) class MockOfflineWlstEnv(model_wdt_mii_filter.OfflineWlstEnv): From 5c78565316c09d6ab10a9dafae7bb3940fcf5ce1 Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Sat, 18 Sep 2021 20:06:54 +0000 Subject: [PATCH 6/9] Remove print statement --- operator/src/main/resources/scripts/model_wdt_mii_filter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/operator/src/main/resources/scripts/model_wdt_mii_filter.py b/operator/src/main/resources/scripts/model_wdt_mii_filter.py index a6e5cfe65f0..28a604e5062 100644 --- a/operator/src/main/resources/scripts/model_wdt_mii_filter.py +++ b/operator/src/main/resources/scripts/model_wdt_mii_filter.py @@ -621,7 +621,6 @@ def nameContainsLocalHostIdentifier(name): endIdentifierIdx = identifierIdx + len(WLS_LOCALHOST_IDENTIFIER) # get substring from localhost identifier to end subStr = name[endIdentifierIdx:] - print subStr # should be only 2 digits 'NN' from '-lhNN' format if len(subStr) == 2: # verify the last two chars are digits From a2f46188e8e7762c16def6ffda7ac4c87438f237 Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Sat, 18 Sep 2021 20:44:00 +0000 Subject: [PATCH 7/9] Python Dict has_key not supported --- operator/src/test/python/test_wdt_mii_filter.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/operator/src/test/python/test_wdt_mii_filter.py b/operator/src/test/python/test_wdt_mii_filter.py index 809f7d4590c..bcc9e697617 100644 --- a/operator/src/test/python/test_wdt_mii_filter.py +++ b/operator/src/test/python/test_wdt_mii_filter.py @@ -304,8 +304,6 @@ def test_createLocalHostNetworkAccessPoint(self): model_wdt_mii_filter.createLocalHostNetworkAccessPoint('T3Channel', nap, nap_name_dict, local_nap_dict) self.assertEqual(1, len(local_nap_dict), "Expected only one dictionary entry") - self.assertTrue(local_nap_dict.has_key('T3Channel' + - model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01')) nap = local_nap_dict['T3Channel' + model_wdt_mii_filter.WLS_LOCALHOST_IDENTIFIER + '01'] self.assertEqual('127.0.0.1', nap['ListenAddress'], From 169785b8c9b51fb1ee3400c75b80e4facc6d3d85 Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Mon, 20 Sep 2021 22:44:44 +0000 Subject: [PATCH 8/9] Changes based on code review --- .../staging/content/userguide/istio/istio.md | 13 ++++++------- .../src/main/resources/scripts/introspectDomain.py | 3 ++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/documentation/staging/content/userguide/istio/istio.md b/documentation/staging/content/userguide/istio/istio.md index 00c758a8350..be530ad3ccc 100644 --- a/documentation/staging/content/userguide/istio/istio.md +++ b/documentation/staging/content/userguide/istio/istio.md @@ -143,13 +143,14 @@ Additionally, when Istio support is enabled for a domain, the operator ensures that the Istio sidecar is not injected into the introspector job's pods. #### Support for network changes in Istio v1.10 and later - -Prior to Istio release 1.10, the Istio Envoy proxy redirected all inbound traffic to the localhost -network interface. The network channels listed above, which the operator automatically added, -were bound to the localhost interface in order for WebLogic to receive the inbound traffic. + Starting with Istio 1.10, the networking behavior was changed in that the proxy no longer redirects the traffic to the localhost interface, but instead forwards it to the network interface associated -to the pod's IP. In order to support Istio v1.10 and later, as well as pre-1.10 releases, the +to the pod's IP. + +To learn more about changes to Istio networking beginning with Istio 1.10, see [Upcoming networking changes in Istio 1.10](https://istio.io/latest/blog/2021/upcoming-networking-changes//). + +In order to support Istio v1.10 and later, as well as previous releases, the operator will: * Add an additional WebLogic HTTP protocol network channel for the readiness probe that is bound to the localhost network interface. @@ -174,8 +175,6 @@ and protocol `t3`, the additional channel would be defined as follows: |----|----|----|--------|-----| |`T3Channel-lh01`| `5556` | `127.0.0.1` | `t3`| Yes | -To learn more about changes to Istio networking beginning with Istio 1.10, see [Upcoming networking changes in Istio 1.10](https://istio.io/latest/blog/2021/upcoming-networking-changes//). - ### Apply the Domain YAML file After the Domain YAML file is modified, apply it by: diff --git a/operator/src/main/resources/scripts/introspectDomain.py b/operator/src/main/resources/scripts/introspectDomain.py index e4d225c09c9..9e08834e96e 100644 --- a/operator/src/main/resources/scripts/introspectDomain.py +++ b/operator/src/main/resources/scripts/introspectDomain.py @@ -1071,7 +1071,8 @@ def writeListenPort(self, listen_port): self.writeln("" + str(listen_port) + "") def writePublicAddress(self, public_address): - self.writeln("" + public_address + "") + if public_address is not None and len(public_address) > 0: + self.writeln("" + public_address + "") def writePublicPort(self, public_port): # offline WLST initializes int values to 0 From 7d277cad2031226a61beb19c37d9ca382b74b2e1 Mon Sep 17 00:00:00 2001 From: Ryan Eberhard Date: Tue, 21 Sep 2021 12:29:48 -0400 Subject: [PATCH 9/9] Update istio.md --- documentation/staging/content/userguide/istio/istio.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/staging/content/userguide/istio/istio.md b/documentation/staging/content/userguide/istio/istio.md index be530ad3ccc..99adc3d7a02 100644 --- a/documentation/staging/content/userguide/istio/istio.md +++ b/documentation/staging/content/userguide/istio/istio.md @@ -146,9 +146,9 @@ ensures that the Istio sidecar is not injected into the introspector job's pods. Starting with Istio 1.10, the networking behavior was changed in that the proxy no longer redirects the traffic to the localhost interface, but instead forwards it to the network interface associated -to the pod's IP. +with the pod's IP. -To learn more about changes to Istio networking beginning with Istio 1.10, see [Upcoming networking changes in Istio 1.10](https://istio.io/latest/blog/2021/upcoming-networking-changes//). +To learn more about changes to Istio networking beginning with Istio 1.10, see [Upcoming networking changes in Istio 1.10](https://istio.io/latest/blog/2021/upcoming-networking-changes/). In order to support Istio v1.10 and later, as well as previous releases, the operator will: