diff --git a/weblogic-azure-aks/pom.xml b/weblogic-azure-aks/pom.xml index affeb4e91..e594b6be1 100644 --- a/weblogic-azure-aks/pom.xml +++ b/weblogic-azure-aks/pom.xml @@ -11,7 +11,7 @@ com.oracle.weblogic.azure wls-on-aks-azure-marketplace - 1.0.16 + 1.0.17 com.microsoft.azure.iaas diff --git a/weblogic-azure-aks/src/main/arm/createUiDefinition.json b/weblogic-azure-aks/src/main/arm/createUiDefinition.json index 66c64fd0f..f0155ca8d 100644 --- a/weblogic-azure-aks/src/main/arm/createUiDefinition.json +++ b/weblogic-azure-aks/src/main/arm/createUiDefinition.json @@ -212,6 +212,30 @@ "required": true }, "visible": "[bool(basics('basicsOptional').basicsOptionalAcceptDefaults)]" + }, + { + "name": "wlsJavaOption", + "type": "Microsoft.Common.TextBox", + "label": "Custom Java Options to start WebLogic Server", + "placeholder": "-Xms1200m -XX:MaxNewSize=300m -Dweblogic.webservice.i18n.charset=utf-8", + "toolTip": "Specify Java options to start WebLogic Server.", + "constraints": { + "regex": "^-[a-z0-9A-Z:./+_=-]+(\\s-[a-z0-9A-Z:./+_=-]+){0,99}$", + "validationMessage": "Allow letters, numbers, space, colon(:), plus(+), minus(-), full stop(.), slash(/), equal sign(=), underscore(_), and the value must be less then 100 Java options." + }, + "visible": "[bool(basics('basicsOptional').basicsOptionalAcceptDefaults)]" + }, + { + "name": "enableAdminT3Tunneling", + "type": "Microsoft.Common.CheckBox", + "label": "Enable T3 tunneling for Admin Server", + "visible": "[bool(basics('basicsOptional').basicsOptionalAcceptDefaults)]" + }, + { + "name": "enableClusterT3Tunneling", + "type": "Microsoft.Common.CheckBox", + "label": "Enable T3 tunneling for WebLogic cluster", + "visible": "[bool(basics('basicsOptional').basicsOptionalAcceptDefaults)]" } ], "visible": true @@ -523,7 +547,7 @@ "type": "Microsoft.Common.TextBlock", "visible": true, "options": { - "text": "Selecting 'Yes' here will cause the template to provision WebLogic Administration Console on HTTPS (Secure) port, with your own TLS/SSL certificate.", + "text": "Selecting 'Yes' here will cause the template to provision WebLogic Administration Console, Remote Console, cluster and custom T3 channel on HTTPS (Secure) port, with your own TLS/SSL certificate.", "link": { "label": "Learn more", "uri": "https://aka.ms/arm-oraclelinux-wls-ssl-config" @@ -971,7 +995,7 @@ "width": "Full", "rows": { "count": { - "min": 1, + "min": 0, "max": 10 } }, @@ -1008,9 +1032,17 @@ "label": "admin-server", "value": "adminServer" }, + { + "label": "admin-server-t3", + "value": "adminServerT3" + }, { "label": "cluster-1", "value": "cluster1" + }, + { + "label": "cluster-1-t3", + "value": "cluster1T3" } ], "required": true @@ -1164,11 +1196,11 @@ { "name": "keyVaultBackendSSLCertData", "type": "Microsoft.Common.FileUpload", - "label": "Trusted root certificate(.cer, cert)", + "label": "Trusted root certificate(.cer, .cert)", "toolTip": "Trusted root certificate (CA certificate) used to set up end to end TLS/SSL", "constraints": { "required": true, - "accept": ".cer, cert" + "accept": ".cer, .cert" }, "options": { "multiple": false, @@ -1306,122 +1338,175 @@ } ], "visible": true + } + ] + }, + { + "name": "section_dnsConfiguration", + "type": "Microsoft.Common.Section", + "label": "DNS Configuration", + "elements": [ + { + "name": "dnsConfigurationText", + "type": "Microsoft.Common.TextBlock", + "visible": true, + "options": { + "text": "Selecting 'Yes' here will cause the template to provision Oracle WebLogic Server Administration Console, cluster, Remote Console and custom T3 channel using custom DNS Name (example: admin.contoso.com)", + "link": { + "label": "Learn more", + "uri": "https://aka.ms/arm-oraclelinux-wls-dns" + } + } }, { - "name": "dnsConfiguration", - "type": "Microsoft.Common.Section", - "label": "Custom DNS Configuration", - "elements": [ - { - "name": "enableDNSConfiguration", - "type": "Microsoft.Common.OptionsGroup", - "label": "Configure Custom DNS Alias", - "defaultValue": "No", - "toolTip": "Select 'Yes' to configure Custom DNS Alias.", - "constraints": { - "allowedValues": [ - { - "label": "Yes", - "value": true - }, - { - "label": "No", - "value": false - } - ], - "required": false + "name": "enableDNSConfiguration", + "type": "Microsoft.Common.OptionsGroup", + "label": "Configure Custom DNS Alias", + "defaultValue": "No", + "toolTip": "Select 'Yes' to configure Custom DNS Alias.", + "constraints": { + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false } - }, - { - "name": "bringDNSZone", - "type": "Microsoft.Common.OptionsGroup", - "label": "Use an existing Azure DNS Zone", - "defaultValue": "No", - "toolTip": "Select 'Yes' to configure Custom DNS Alias based on an existing Azure DNS Zone. Select 'No' to create an Azure DNS Zone and Custom DNS Alias.", - "constraints": { - "allowedValues": [ - { - "label": "Yes", - "value": true - }, - { - "label": "No", - "value": false - } - ] + ], + "required": false + } + }, + { + "name": "bringDNSZone", + "type": "Microsoft.Common.OptionsGroup", + "label": "Use an existing Azure DNS Zone", + "defaultValue": "No", + "toolTip": "Select 'Yes' to configure Custom DNS Alias based on an existing Azure DNS Zone. Select 'No' to create an Azure DNS Zone and Custom DNS Alias.", + "constraints": { + "allowedValues": [ + { + "label": "Yes", + "value": true }, - "visible": "[steps('section_appGateway').dnsConfiguration.enableDNSConfiguration]" - }, - { - "name": "dnszoneName", - "type": "Microsoft.Common.TextBox", - "label": "DNS Zone Name", - "defaultValue": "", - "toolTip": "Use only letters and numbers and periods to separate Domains", - "constraints": { - "required": true, - "regex": "^([0-9a-zA-Z_-]{1,63}\\.){1,33}[0-9a-zA-Z_-]{1,63}$", - "validationMessage": "There must be between 2 and 34 labels. For example, \"contoso.com\" has 2 labels. Each label must contain between 1 and 63 characters. Each label must only contain letters, numbers, underscores, and dashes." + { + "label": "No", + "value": false + } + ] + }, + "visible": "[steps('section_dnsConfiguration').enableDNSConfiguration]" + }, + { + "name": "dnszoneName", + "type": "Microsoft.Common.TextBox", + "label": "DNS Zone Name", + "defaultValue": "", + "toolTip": "Use only letters and numbers and periods to separate Domains", + "constraints": { + "required": true, + "regex": "^([0-9a-zA-Z_-]{1,63}\\.){1,33}[0-9a-zA-Z_-]{1,63}$", + "validationMessage": "There must be between 2 and 34 labels. For example, \"contoso.com\" has 2 labels. Each label must contain between 1 and 63 characters. Each label must only contain letters, numbers, underscores, and dashes." + }, + "visible": "[steps('section_dnsConfiguration').enableDNSConfiguration]" + }, + { + "name": "dnsZoneResourceGroup", + "type": "Microsoft.Common.TextBox", + "label": "Name of the resource group contains the DNS Zone in current subscription", + "defaultValue": "", + "toolTip": "Name of the resource group which contains the DNS Zone in current subscription", + "constraints": { + "required": true, + "regex": "^[a-z0-9A-Z.\\-_()]{0,89}([a-z0-9A-Z\\-_()]{1})$", + "validationMessage": "[if(greater(length(steps('section_dnsConfiguration').dnsZoneResourceGroup), 90),'Resource group names only allow up to 90 characters.', 'Resource group names only allow alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.')]" + }, + "visible": "[and(steps('section_dnsConfiguration').enableDNSConfiguration,steps('section_dnsConfiguration').bringDNSZone)]" + }, + { + "name": "dnszoneAdminConsoleLabel", + "type": "Microsoft.Common.TextBox", + "label": "Label for Oracle WebLogic Administration Console", + "defaultValue": "admin", + "toolTip": "Specify a label to generate subdomain of Oracle WebLogic Administration Console", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^([0-9a-zA-Z_-]{1,63}\\.){0,33}[0-9a-zA-Z_-]{1,63}$", + "message": "Each label must contain between 1 and 63 characters. Each label must only contain letters, numbers, underscores, and dashes." }, - "visible": "[steps('section_appGateway').dnsConfiguration.enableDNSConfiguration]" - }, - { - "name": "dnsZoneResourceGroup", - "type": "Microsoft.Common.TextBox", - "label": "Name of the resource group contains the DNS Zone in current subscription", - "defaultValue": "", - "toolTip": "Name of the resource group which contains the DNS Zone in current subscription", - "constraints": { - "required": true, - "regex": "^[a-z0-9A-Z.\\-_()]{0,89}([a-z0-9A-Z\\-_()]{1})$", - "validationMessage": "[if(greater(length(steps('section_appGateway').dnsConfiguration.dnsZoneResourceGroup), 90),'Resource group names only allow up to 90 characters.', 'Resource group names only allow alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.')]" + { + "isValid": "[less(sub(length(concat(steps('section_dnsConfiguration').dnszoneAdminConsoleLabel,'.',steps('section_dnsConfiguration').dnszoneName)),length(replace(concat(steps('section_dnsConfiguration').dnszoneAdminConsoleLabel,'.',steps('section_dnsConfiguration').dnszoneName), '.', ''))),34)]", + "message": "Subdomain must be between 2 and 34 labels. For example, \"admin.contoso.com\" has 3 labels." + } + ] + }, + "visible": "[steps('section_dnsConfiguration').enableDNSConfiguration]" + }, + { + "name": "dnszoneAdminT3ChannelLabel", + "type": "Microsoft.Common.TextBox", + "label": "Label for Oracle WebLogic Admin Server T3 channel", + "defaultValue": "admin-t3", + "toolTip": "Specify a label to generate subdomain of Oracle WebLogic Admin Server T3 channel", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^([0-9a-zA-Z_-]{1,63}\\.){0,33}[0-9a-zA-Z_-]{1,63}$", + "message": "Each label must contain between 1 and 63 characters. Each label must only contain letters, numbers, underscores, and dashes." }, - "visible": "[and(steps('section_appGateway').dnsConfiguration.enableDNSConfiguration,steps('section_appGateway').dnsConfiguration.bringDNSZone)]" - }, - { - "name": "dnszoneAdminConsoleLabel", - "type": "Microsoft.Common.TextBox", - "label": "Label for Oracle WebLogic Administration Console", - "defaultValue": "admin", - "toolTip": "Specify a label to generate subdomain of Oracle WebLogic Administration Console", - "constraints": { - "required": true, - "validations": [ - { - "regex": "^([0-9a-zA-Z_-]{1,63}\\.){0,33}[0-9a-zA-Z_-]{1,63}$", - "message": "Each label must contain between 1 and 63 characters. Each label must only contain letters, numbers, underscores, and dashes." - }, - { - "isValid": "[less(sub(length(concat(steps('section_appGateway').dnsConfiguration.dnszoneAdminConsoleLabel,'.',steps('section_appGateway').dnsConfiguration.dnszoneName)),length(replace(concat(steps('section_appGateway').dnsConfiguration.dnszoneAdminConsoleLabel,'.',steps('section_appGateway').dnsConfiguration.dnszoneName), '.', ''))),34)]", - "message": "Subdomain must be between 2 and 34 labels. For example, \"admin.contoso.com\" has 3 labels." - } - ] + { + "isValid": "[less(sub(length(concat(steps('section_dnsConfiguration').dnszoneAdminT3ChannelLabel,'.',steps('section_dnsConfiguration').dnszoneName)),length(replace(concat(steps('section_dnsConfiguration').dnszoneAdminT3ChannelLabel,'.',steps('section_dnsConfiguration').dnszoneName), '.', ''))),34)]", + "message": "Subdomain must be between 2 and 34 labels. For example, \"admin-t3.contoso.com\" has 3 labels." + } + ] + }, + "visible": "[and(steps('section_dnsConfiguration').enableDNSConfiguration,basics('basicsOptional').enableAdminT3Tunneling, steps('section_appGateway').lbSVCInfo.enableLBSVC)]" + }, + { + "name": "dnszoneGatewayLabel", + "type": "Microsoft.Common.TextBox", + "label": "Label for WebLogic Cluster", + "defaultValue": "www", + "toolTip": "Specify a label to generate subdomain of WebLogic Cluster", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^([0-9a-zA-Z_-]{1,63}\\.){0,33}[0-9a-zA-Z_-]{1,63}$", + "message": "Each label must contain between 1 and 63 characters. Each label must only contain letters, numbers, underscores, and dashes." }, - "visible": "[steps('section_appGateway').dnsConfiguration.enableDNSConfiguration]" - }, - { - "name": "dnszoneGatewayLabel", - "type": "Microsoft.Common.TextBox", - "label": "Label for WebLogic Cluster", - "defaultValue": "www", - "toolTip": "Specify a label to generate subdomain of WebLogic Cluster", - "constraints": { - "required": true, - "validations": [ - { - "regex": "^([0-9a-zA-Z_-]{1,63}\\.){0,33}[0-9a-zA-Z_-]{1,63}$", - "message": "Each label must contain between 1 and 63 characters. Each label must only contain letters, numbers, underscores, and dashes." - }, - { - "isValid": "[less(sub(length(concat(if(empty(steps('section_appGateway').dnsConfiguration.dnszoneGatewayLabel), '', steps('section_appGateway').dnsConfiguration.dnszoneGatewayLabel),'.',steps('section_appGateway').dnsConfiguration.dnszoneName)),length(replace(concat(if(empty(steps('section_appGateway').dnsConfiguration.dnszoneGatewayLabel), '', steps('section_appGateway').dnsConfiguration.dnszoneGatewayLabel),'.',steps('section_appGateway').dnsConfiguration.dnszoneName), '.', ''))),34)]", - "message": "Subdomain must be between 2 and 34 labels. For example, \"applications.contoso.com\" has 3 labels." - } - ] + { + "isValid": "[less(sub(length(concat(if(empty(steps('section_dnsConfiguration').dnszoneGatewayLabel), '', steps('section_dnsConfiguration').dnszoneGatewayLabel),'.',steps('section_dnsConfiguration').dnszoneName)),length(replace(concat(if(empty(steps('section_dnsConfiguration').dnszoneGatewayLabel), '', steps('section_dnsConfiguration').dnszoneGatewayLabel),'.',steps('section_dnsConfiguration').dnszoneName), '.', ''))),34)]", + "message": "Subdomain must be between 2 and 34 labels. For example, \"applications.contoso.com\" has 3 labels." + } + ] + }, + "visible": "[steps('section_dnsConfiguration').enableDNSConfiguration]" + }, + { + "name": "dnszoneClusterT3ChannelLabel", + "type": "Microsoft.Common.TextBox", + "label": "Label for Oracle WebLogic cluster T3 channel", + "defaultValue": "cluster-t3", + "toolTip": "Specify a label to generate subdomain of Oracle WebLogic cluster T3 channel", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^([0-9a-zA-Z_-]{1,63}\\.){0,33}[0-9a-zA-Z_-]{1,63}$", + "message": "Each label must contain between 1 and 63 characters. Each label must only contain letters, numbers, underscores, and dashes." }, - "visible": "[steps('section_appGateway').dnsConfiguration.enableDNSConfiguration]" - } - ], - "visible": true + { + "isValid": "[less(sub(length(concat(steps('section_dnsConfiguration').dnszoneClusterT3ChannelLabel,'.',steps('section_dnsConfiguration').dnszoneName)),length(replace(concat(steps('section_dnsConfiguration').dnszoneClusterT3ChannelLabel,'.',steps('section_dnsConfiguration').dnszoneName), '.', ''))),34)]", + "message": "Subdomain must be between 2 and 34 labels. For example, \"application-t3.contoso.com\" has 3 labels." + } + ] + }, + "visible": "[and(steps('section_dnsConfiguration').enableDNSConfiguration,basics('basicsOptional').enableClusterT3Tunneling, steps('section_appGateway').lbSVCInfo.enableLBSVC)]" } ] }, @@ -1571,14 +1656,16 @@ "appReplicas": "[int(steps('section_aks').jeeAppInfo.appReplicas)]", "createACR": "[bool(steps('section_aks').acrInfo.createACR)]", "createAKSCluster": "[bool(steps('section_aks').clusterInfo.createAKSCluster)]", - "createDNSZone": "[not(bool(steps('section_appGateway').dnsConfiguration.bringDNSZone))]", + "createDNSZone": "[not(bool(steps('section_dnsConfiguration').bringDNSZone))]", "dbPassword": "[steps('section_database').databaseConnectionInfo.dbPassword]", "dbUser": "[steps('section_database').databaseConnectionInfo.dbUser]", "databaseType": "[steps('section_database').databaseConnectionInfo.databaseType]", - "dnszoneAdminConsoleLabel": "[steps('section_appGateway').dnsConfiguration.dnszoneAdminConsoleLabel]", - "dnszoneAppGatewayLabel": "[steps('section_appGateway').dnsConfiguration.dnszoneGatewayLabel]", - "dnszoneName": "[steps('section_appGateway').dnsConfiguration.dnszoneName]", - "dnszoneRGName": "[steps('section_appGateway').dnsConfiguration.dnsZoneResourceGroup]", + "dnszoneAdminConsoleLabel": "[steps('section_dnsConfiguration').dnszoneAdminConsoleLabel]", + "dnszoneAdminT3ChannelLabel": "[steps('section_dnsConfiguration').dnszoneAdminT3ChannelLabel]", + "dnszoneClusterLabel": "[steps('section_dnsConfiguration').dnszoneGatewayLabel]", + "dnszoneClusterT3ChannelLabel": "[steps('section_dnsConfiguration').dnszoneClusterT3ChannelLabel]", + "dnszoneName": "[steps('section_dnsConfiguration').dnszoneName]", + "dnszoneRGName": "[steps('section_dnsConfiguration').dnsZoneResourceGroup]", "dsConnectionURL": "[steps('section_database').databaseConnectionInfo.dsConnectionURL]", "enableAppGWIngress": "[steps('section_appGateway').appgwIngress.enableAppGateway]", "enableAzureMonitoring": "[bool(steps('section_aks').clusterInfo.enableAzureMonitoring)]", @@ -1586,7 +1673,9 @@ "enableCookieBasedAffinity": "[bool(steps('section_appGateway').appgwIngress.enableCookieBasedAffinity)]", "enableCustomSSL": "[bool(steps('section_sslConfiguration').enableCustomSSL)]", "enableDB": "[bool(steps('section_database').enableDB)]", - "enableDNSConfiguration": "[bool(steps('section_appGateway').dnsConfiguration.enableDNSConfiguration)]", + "enableDNSConfiguration": "[bool(steps('section_dnsConfiguration').enableDNSConfiguration)]", + "enableAdminT3Tunneling": "[basics('basicsOptional').enableAdminT3Tunneling]", + "enableClusterT3Tunneling": "[basics('basicsOptional').enableClusterT3Tunneling]", "identity": "[basics('basicsRequired').identity]", "jdbcDataSourceName": "[steps('section_database').databaseConnectionInfo.jdbcDataSourceName]", "lbSvcValues": "[steps('section_appGateway').lbSVCInfo.lbSVC]", @@ -1625,6 +1714,7 @@ "wlsDomainName": "[basics('basicsOptional').wlsDomainName]", "wlsDomainUID": "[basics('basicsOptional').wlsDomainUID]", "wlsImageTag": "[steps('section_aks').imageInfo.fromImage]", + "wlsJavaOption": "[basics('basicsOptional').wlsJavaOption]", "wlsPassword": "[basics('basicsRequired').wlsPassword]", "wlsUserName": "[basics('basicsRequired').wlsUserName]" } diff --git a/weblogic-azure-aks/src/main/arm/scripts/buildWLSDockerImage.sh b/weblogic-azure-aks/src/main/arm/scripts/buildWLSDockerImage.sh index 3c19e2cb5..0694ebe0d 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/buildWLSDockerImage.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/buildWLSDockerImage.sh @@ -15,7 +15,7 @@ function read_sensitive_parameters_from_stdin() { #Function to display usage message function usage() { - echo " ./buildWLSDockerImage.sh ./buildWLSDockerImage.sh " + echo " ./buildWLSDockerImage.sh ./buildWLSDockerImage.sh " if [ $1 -eq 1 ]; then exit 1 fi @@ -80,6 +80,16 @@ function validate_inputs() { echo_stderr "enableSSL is required. " usage 1 fi + + if [ -z "$enableAdminT3Tunneling" ]; then + echo_stderr "enableAdminT3Tunneling is required. " + usage 1 + fi + + if [ -z "$enableClusterT3Tunneling" ]; then + echo_stderr "enableClusterT3Tunneling is required. " + usage 1 + fi } function initialize() { @@ -179,7 +189,9 @@ EOF bash $scriptDir/genImageModel.sh \ ${modelFilePath} \ ${appPackageUrls} \ - ${enableSSL} + ${enableSSL} \ + ${enableAdminT3Tunneling} \ + ${enableClusterT3Tunneling} validate_status "Generate image model file." } @@ -236,11 +248,13 @@ export appPackageUrls=$5 export ocrSSOUser=$6 export wlsClusterSize=$7 export enableSSL=$8 +export enableAdminT3Tunneling=$9 +export enableClusterT3Tunneling=${10} export acrImagePath="$azureACRServer/aks-wls-images:${imageTag}" export ocrLoginServer="container-registry.oracle.com" -export wdtDownloadURL="https://github.com/oracle/weblogic-deploy-tooling/releases/download/release-1.9.14/weblogic-deploy.zip" -export witDownloadURL="https://github.com/oracle/weblogic-image-tool/releases/download/release-1.9.12/imagetool.zip" +export wdtDownloadURL="https://github.com/oracle/weblogic-deploy-tooling/releases/download/release-1.9.17/weblogic-deploy.zip" +export witDownloadURL="https://github.com/oracle/weblogic-image-tool/releases/download/release-1.9.16/imagetool.zip" export wlsPostgresqlDriverUrl="https://jdbc.postgresql.org/download/postgresql-42.2.8.jar" export wlsMSSQLDriverUrl="https://repo.maven.apache.org/maven2/com/microsoft/sqlserver/mssql-jdbc/7.4.1.jre8/mssql-jdbc-7.4.1.jre8.jar" diff --git a/weblogic-azure-aks/src/main/arm/scripts/common.sh b/weblogic-azure-aks/src/main/arm/scripts/common.sh index f985e809f..dcf214f3d 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/common.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/common.sh @@ -2,7 +2,13 @@ export checkPodStatusInterval=20 # interval of checking pod status. export checkPodStatusMaxAttemps=30 # max attempt to check pod status. export checkPVStateInterval=5 # interval of checking pvc status. export checkPVStateMaxAttempt=10 # max attempt to check pvc status. +export checkSVCStateMaxAttempt=10 +export checkSVCInterval=30 #seconds +export constAdminT3AddressEnvName="T3_TUNNELING_ADMIN_ADDRESS" +export constAdminServerName='admin-server' +export constClusterName='cluster-1' +export constClusterT3AddressEnvName="T3_TUNNELING_CLUSTER_ADDRESS" export constFalse="false" export constTrue="true" diff --git a/weblogic-azure-aks/src/main/arm/scripts/createAppGatewayIngress.sh b/weblogic-azure-aks/src/main/arm/scripts/createAppGatewayIngress.sh new file mode 100644 index 000000000..ba1ec299e --- /dev/null +++ b/weblogic-azure-aks/src/main/arm/scripts/createAppGatewayIngress.sh @@ -0,0 +1,639 @@ +# Copyright (c) 2021, Oracle Corporation and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# Description: to create Azure Application Gateway ingress for the following targets. +# * [Optional] Admin console, with path host/console +# * [Optional] Admin remote console, with path host/remoteconsole +# * Cluster, with path host/* + +echo "Script ${0} starts" + +# read from stdin +function read_sensitive_parameters_from_stdin() { + read spBase64String appgwFrontendSSLCertPsw +} + +function generate_appgw_cluster_config_file_expose_https() { + clusterIngressHttpsName=${wlsDomainUID}-cluster-appgw-ingress-https-svc + clusterAppgwIngressHttpsYamlPath=${scriptDir}/appgw-cluster-ingress-https-svc.yaml + cat <${clusterAppgwIngressHttpsYamlPath} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ${clusterIngressHttpsName} + namespace: ${wlsDomainNS} + annotations: + kubernetes.io/ingress.class: azure/application-gateway +EOF + + if [[ "${enableCookieBasedAffinity,,}" == "true" ]]; then + cat <>${clusterAppgwIngressHttpsYamlPath} + appgw.ingress.kubernetes.io/cookie-based-affinity: "true" +EOF + fi + + cat <>${clusterAppgwIngressHttpsYamlPath} +spec: + tls: + - secretName: ${appgwFrontendSecretName} + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ${svcCluster} + port: + number: ${clusterTargetPort} +EOF +} + +function generate_appgw_cluster_config_file_nossl() { + clusterIngressName=${wlsDomainUID}-cluster-appgw-ingress-svc + clusterAppgwIngressYamlPath=${scriptDir}/appgw-cluster-ingress-svc.yaml + cat <${clusterAppgwIngressYamlPath} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ${clusterIngressName} + namespace: ${wlsDomainNS} + annotations: + kubernetes.io/ingress.class: azure/application-gateway +EOF + + if [[ "${enableCookieBasedAffinity,,}" == "true" ]]; then + cat <>${clusterAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/cookie-based-affinity: "true" +EOF + fi + + cat <>${clusterAppgwIngressYamlPath} +spec: + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ${svcCluster} + port: + number: ${clusterTargetPort} +EOF +} + +function generate_appgw_cluster_config_file_ssl() { + clusterIngressName=${wlsDomainUID}-cluster-appgw-ingress-svc + clusterAppgwIngressYamlPath=${scriptDir}/appgw-cluster-ingress-svc.yaml + cat <${clusterAppgwIngressYamlPath} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ${clusterIngressName} + namespace: ${wlsDomainNS} + annotations: + kubernetes.io/ingress.class: azure/application-gateway + appgw.ingress.kubernetes.io/ssl-redirect: "true" + appgw.ingress.kubernetes.io/backend-protocol: "https" +EOF + if [[ "${enableCustomDNSAlias,,}" == "true" ]]; then + cat <>${clusterAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/backend-hostname: "${dnsClusterLabel}.${dnsZoneName}" +EOF + else + cat <>${clusterAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/backend-hostname: "${appgwAlias}" +EOF + fi + + if [[ "${enableCookieBasedAffinity,,}" == "true" ]]; then + cat <>${clusterAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/cookie-based-affinity: "true" +EOF + fi + + cat <>${clusterAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/appgw-trusted-root-certificate: "${appgwBackendSecretName}" + +spec: + tls: + - secretName: ${appgwFrontendSecretName} + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ${svcCluster} + port: + number: ${clusterTargetPort} +EOF +} + +function generate_appgw_admin_config_file_nossl() { + adminIngressName=${wlsDomainUID}-admin-appgw-ingress-svc + adminAppgwIngressYamlPath=${scriptDir}/appgw-admin-ingress-svc.yaml + cat <${adminAppgwIngressYamlPath} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ${adminIngressName} + namespace: ${wlsDomainNS} + annotations: + kubernetes.io/ingress.class: azure/application-gateway +EOF + + if [[ "${enableCookieBasedAffinity,,}" == "true" ]]; then + cat <>${adminAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/cookie-based-affinity: "true" +EOF + fi + + cat <>${adminAppgwIngressYamlPath} +spec: + rules: + - http: + paths: + - path: /console* + pathType: Prefix + backend: + service: + name: ${svcAdminServer} + port: + number: ${adminTargetPort} +EOF +} + +function generate_appgw_admin_remote_config_file_nossl() { + cat <${adminRemoteAppgwIngressYamlPath} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ${adminRemoteIngressName} + namespace: ${wlsDomainNS} + annotations: + kubernetes.io/ingress.class: azure/application-gateway + appgw.ingress.kubernetes.io/backend-path-prefix: "/" +EOF + + if [[ "${enableCookieBasedAffinity,,}" == "true" ]]; then + cat <>${adminRemoteAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/cookie-based-affinity: "true" +EOF + fi + + cat <>${adminRemoteAppgwIngressYamlPath} +spec: + rules: + - http: + paths: + - path: /remoteconsole* + pathType: Prefix + backend: + service: + name: ${svcAdminServer} + port: + number: ${adminTargetPort} +EOF +} + +function generate_appgw_admin_config_file_ssl() { + adminIngressName=${wlsDomainUID}-admin-appgw-ingress-svc + adminAppgwIngressYamlPath=${scriptDir}/appgw-admin-ingress-svc.yaml + cat <${adminAppgwIngressYamlPath} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ${adminIngressName} + namespace: ${wlsDomainNS} + annotations: + kubernetes.io/ingress.class: azure/application-gateway + appgw.ingress.kubernetes.io/ssl-redirect: "true" + appgw.ingress.kubernetes.io/backend-protocol: "https" +EOF + + if [[ "${enableCustomDNSAlias,,}" == "true" ]]; then + cat <>${adminAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/backend-hostname: "${dnsAdminLabel}.${dnsZoneName}" +EOF + else + cat <>${adminAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/backend-hostname: "${appgwAlias}" +EOF + fi + + if [[ "${enableCookieBasedAffinity,,}" == "true" ]]; then + cat <>${adminAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/cookie-based-affinity: "true" +EOF + fi + + cat <>${adminAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/appgw-trusted-root-certificate: "${appgwBackendSecretName}" + +spec: + tls: + - secretName: ${appgwFrontendSecretName} + rules: + - http: + paths: + - path: /console* + pathType: Prefix + backend: + service: + name: ${svcAdminServer} + port: + number: ${adminTargetPort} +EOF +} + +function generate_appgw_admin_remote_config_file_ssl() { + cat <${adminRemoteAppgwIngressYamlPath} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ${adminRemoteIngressName} + namespace: ${wlsDomainNS} + annotations: + kubernetes.io/ingress.class: azure/application-gateway + appgw.ingress.kubernetes.io/backend-path-prefix: "/" + appgw.ingress.kubernetes.io/ssl-redirect: "true" + appgw.ingress.kubernetes.io/backend-protocol: "https" + +EOF + + if [[ "${enableCustomDNSAlias,,}" == "true" ]]; then + cat <>${adminRemoteAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/backend-hostname: "${dnsAdminLabel}.${dnsZoneName}" +EOF + else + cat <>${adminRemoteAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/backend-hostname: "${appgwAlias}" +EOF + fi + + if [[ "${enableCookieBasedAffinity,,}" == "true" ]]; then + cat <>${adminRemoteAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/cookie-based-affinity: "true" +EOF + fi + + cat <>${adminRemoteAppgwIngressYamlPath} + appgw.ingress.kubernetes.io/appgw-trusted-root-certificate: "${appgwBackendSecretName}" + +spec: + tls: + - secretName: ${appgwFrontendSecretName} + rules: + - http: + paths: + - path: /remoteconsole* + pathType: Prefix + backend: + service: + name: ${svcAdminServer} + port: + number: ${adminTargetPort} +EOF +} + +function query_admin_target_port() { + if [[ "${enableCustomSSL,,}" == "true" ]]; then + adminTargetPort=$(utility_query_service_port ${svcAdminServer} ${wlsDomainNS} 'default-secure') + else + adminTargetPort=$(utility_query_service_port ${svcAdminServer} ${wlsDomainNS} 'default') + fi + + echo "Admin port of ${adminServerName}: ${adminTargetPort}" +} + +# Create network peers for aks and appgw +function network_peers_aks_appgw() { + # To successfully peer two virtual networks command 'az network vnet peering create' must be called twice with the values + # for --vnet-name and --remote-vnet reversed. + aksMCRGName=$(az aks show -n $aksClusterName -g $aksClusterRGName -o tsv --query "nodeResourceGroup") + ret=$(az group exists -n ${aksMCRGName}) + if [ "${ret,,}" == "false" ]; then + echo_stderr "AKS namaged resource group ${aksMCRGName} does not exist." + exit 1 + fi + + aksNetWorkId=$(az resource list -g ${aksMCRGName} --resource-type Microsoft.Network/virtualNetworks -o tsv --query '[*].id') + aksNetworkName=$(az resource list -g ${aksMCRGName} --resource-type Microsoft.Network/virtualNetworks -o tsv --query '[*].name') + az network vnet peering create \ + --name aks-appgw-peer \ + --remote-vnet ${aksNetWorkId} \ + --resource-group ${curRGName} \ + --vnet-name ${vnetName} \ + --allow-vnet-access + utility_validate_status "Create network peers for $aksNetWorkId and ${vnetName}." + + appgwNetworkId=$(az resource list -g ${curRGName} --name ${vnetName} -o tsv --query '[*].id') + az network vnet peering create \ + --name aks-appgw-peer \ + --remote-vnet ${appgwNetworkId} \ + --resource-group ${aksMCRGName} \ + --vnet-name ${aksNetworkName} \ + --allow-vnet-access + + utility_validate_status "Create network peers for $aksNetWorkId and ${vnetName}." + + # For Kbectl network plugin: https://azure.github.io/application-gateway-kubernetes-ingress/how-tos/networking/#with-kubenet + # find route table used by aks cluster + routeTableId=$(az network route-table list -g $aksMCRGName --query "[].id | [0]" -o tsv) + + # get the application gateway's subnet + appGatewaySubnetId=$(az network application-gateway show -n $appgwName -g $curRGName -o tsv --query "gatewayIpConfigurations[0].subnet.id") + + # associate the route table to Application Gateway's subnet + az network vnet subnet update \ + --ids $appGatewaySubnetId \ + --route-table $routeTableId + + utility_validate_status "Associate the route table ${routeTableId} to Application Gateway's subnet ${appGatewaySubnetId}" +} + +function query_cluster_target_port() { + if [[ "${enableCustomSSL,,}" == "true" ]]; then + clusterTargetPort=$(utility_query_service_port ${svcCluster} ${wlsDomainNS} 'default-secure') + else + clusterTargetPort=$(utility_query_service_port ${svcCluster} ${wlsDomainNS} 'default') + fi + + echo "Cluster port of ${clusterName}: ${clusterTargetPort}" +} + +function install_azure_ingress() { + # create sa and bind cluster-admin role + # grant azure ingress permission to access WebLogic service + kubectl apply -f ${scriptDir}/appgw-ingress-clusterAdmin-roleBinding.yaml + + install_helm + helm repo add application-gateway-kubernetes-ingress ${appgwIngressHelmRepo} + helm repo update + + # generate Helm config for azure ingress + customAppgwHelmConfig=${scriptDir}/appgw-helm-config.yaml + cp ${scriptDir}/appgw-helm-config.yaml.template ${customAppgwHelmConfig} + subID=${subID#*\/subscriptions\/} + sed -i -e "s:@SUB_ID@:${subID}:g" ${customAppgwHelmConfig} + sed -i -e "s:@APPGW_RG_NAME@:${curRGName}:g" ${customAppgwHelmConfig} + sed -i -e "s:@APPGW_NAME@:${appgwName}:g" ${customAppgwHelmConfig} + sed -i -e "s:@WATCH_NAMESPACE@:${wlsDomainNS}:g" ${customAppgwHelmConfig} + sed -i -e "s:@SP_ENCODING_CREDENTIALS@:${spBase64String}:g" ${customAppgwHelmConfig} + + helm install ingress-azure \ + -f ${customAppgwHelmConfig} \ + application-gateway-kubernetes-ingress/ingress-azure \ + --version ${azureAppgwIngressVersion} + + utility_validate_status "Install app gateway ingress controller." + + attempts=0 + podState="running" + while [ "$podState" == "running" ] && [ $attempts -lt ${checkPodStatusMaxAttemps} ]; do + podState="completed" + attempts=$((attempts + 1)) + echo Waiting for Pod running...${attempts} + sleep ${checkPodStatusInterval} + + ret=$(kubectl get pod -o json | + jq '.items[] | .status.containerStatuses[] | select(.name=="ingress-azure") | .ready') + if [[ "${ret}" == "false" ]]; then + podState="running" + fi + done + + if [ "$podState" == "running" ] && [ $attempts -ge ${checkPodStatusMaxAttemps} ]; then + echo_stderr "Failed to install app gateway ingress controller." + exit 1 + fi +} + +function output_create_gateway_ssl_k8s_secret() { + echo "export gateway frontend certificates" + echo "$appgwFrontendSSLCertData" | base64 -d >${scriptDir}/$appgwFrontCertFileName + + appgwFrontendSSLCertPassin=${appgwFrontendSSLCertPsw} + if [[ "$appgwCertificateOption" == "${appgwSelfsignedCert}" ]]; then + appgwFrontendSSLCertPassin="" # empty password + fi + + openssl pkcs12 \ + -in ${scriptDir}/$appgwFrontCertFileName \ + -nocerts \ + -out ${scriptDir}/$appgwFrontCertKeyFileName \ + -passin pass:${appgwFrontendSSLCertPassin} \ + -passout pass:${appgwFrontendSSLCertPsw} + + utility_validate_status "Export key from frontend certificate." + + openssl rsa -in ${scriptDir}/$appgwFrontCertKeyFileName \ + -out ${scriptDir}/$appgwFrontCertKeyDecrytedFileName \ + -passin pass:${appgwFrontendSSLCertPsw} + + utility_validate_status "Decryte private key." + + openssl pkcs12 \ + -in ${scriptDir}/$appgwFrontCertFileName \ + -clcerts \ + -nokeys \ + -out ${scriptDir}/$appgwFrontPublicCertFileName \ + -passin pass:${appgwFrontendSSLCertPassin} + + utility_validate_status "Export cert from frontend certificate." + + echo "create k8s tsl secret for app gateway frontend ssl termination" + kubectl -n ${wlsDomainNS} create secret tls ${appgwFrontendSecretName} \ + --key="${scriptDir}/$appgwFrontCertKeyDecrytedFileName" \ + --cert="${scriptDir}/$appgwFrontPublicCertFileName" + + utility_validate_status "create k8s tsl secret for app gateway frontend ssl termination." +} + +function validate_backend_ca_cert() { + az network application-gateway root-cert list \ + --gateway-name $appgwName \ + --resource-group $curRGName | + jq '.[] | .name' | grep "${appgwBackendSecretName}" + + utility_validate_status "check if backend cert exists." +} + +function generate_appgw_cluster_config_file() { + if [[ "${enableCustomSSL,,}" == "true" ]]; then + generate_appgw_cluster_config_file_ssl + else + generate_appgw_cluster_config_file_nossl + generate_appgw_cluster_config_file_expose_https + fi +} + +function generate_appgw_admin_config_file() { + if [[ "${enableCustomSSL,,}" == "true" ]]; then + generate_appgw_admin_config_file_ssl + else + generate_appgw_admin_config_file_nossl + fi +} + +function generate_appgw_admin_remote_config_file() { + if [[ "${enableCustomSSL,,}" == "true" ]]; then + generate_appgw_admin_remote_config_file_ssl + else + generate_appgw_admin_remote_config_file_nossl + fi +} + +function appgw_ingress_svc_for_cluster() { + # generate ingress svc config for cluster + generate_appgw_cluster_config_file + kubectl apply -f ${clusterAppgwIngressYamlPath} + utility_validate_status "Create appgw ingress svc." + utility_waitfor_lb_svc_completed \ + ${clusterIngressName} \ + ${wlsDomainNS} \ + ${checkSVCStateMaxAttempt} \ + ${checkSVCInterval} + + # expose https for cluster if e2e ssl is not set up. + if [[ "${enableCustomSSL,,}" != "true" ]]; then + kubectl apply -f ${clusterAppgwIngressHttpsYamlPath} + utility_validate_status "Create appgw ingress https svc." + utility_waitfor_lb_svc_completed \ + ${clusterIngressHttpsName} \ + ${wlsDomainNS} \ + ${checkSVCStateMaxAttempt} \ + ${checkSVCInterval} + fi +} + +function appgw_ingress_svc_for_admin_server() { + generate_appgw_admin_config_file + kubectl apply -f ${adminAppgwIngressYamlPath} + utility_validate_status "Create appgw ingress svc." + utility_waitfor_lb_svc_completed \ + ${adminIngressName} \ + ${wlsDomainNS} \ + ${checkSVCStateMaxAttempt} \ + ${checkSVCInterval} +} + +function appgw_ingress_svc_for_remote_console() { + adminRemoteIngressName=${wlsDomainUID}-admin-remote-appgw-ingress-svc + adminRemoteAppgwIngressYamlPath=${scriptDir}/appgw-admin-remote-ingress-svc.yaml + generate_appgw_admin_remote_config_file + + kubectl apply -f ${adminRemoteAppgwIngressYamlPath} + utility_validate_status "Create appgw ingress svc." + utility_waitfor_lb_svc_completed \ + ${adminRemoteIngressName} \ + ${wlsDomainNS} \ + ${checkSVCStateMaxAttempt} \ + ${checkSVCInterval} +} + +function create_dns_record() { + if [[ "${enableCustomDNSAlias,,}" == "true" ]]; then + create_dns_CNAME_record \ + ${appgwAlias} \ + ${dnsClusterLabel} \ + ${dnsRGName} \ + ${dnsZoneName} + fi + + if [[ "${enableCustomDNSAlias,,}" == "true" ]] && + [[ "${appgwForAdminServer,,}" == "true" ]]; then + create_dns_CNAME_record \ + ${appgwAlias} \ + ${dnsAdminLabel} \ + ${dnsRGName} \ + ${dnsZoneName} + fi +} + +function create_gateway_ingress() { + # query admin server port used for non-ssl or ssl + query_admin_target_port + # query cluster port used for non-ssl or ssl + query_cluster_target_port + # create network peers between gateway vnet and aks vnet + network_peers_aks_appgw + # install azure ingress controllor + install_azure_ingress + # create tsl/ssl frontend secrets + output_create_gateway_ssl_k8s_secret + + # validate backend CA certificate + # the certificate has been upload to Application Gateway in + # weblogic-azure-aks\src\main\bicep\modules\networking.bicep + if [[ "${enableCustomSSL,,}" == "true" ]]; then + validate_backend_ca_cert + fi + + # create ingress svc for cluster + appgw_ingress_svc_for_cluster + + # create ingress svc for admin console + if [[ "${appgwForAdminServer,,}" == "true" ]]; then + appgw_ingress_svc_for_admin_server + fi + + # create ingress svc for admin remote console + if [[ "${enableRemoteConsole,,}" == "true" ]]; then + appgw_ingress_svc_for_remote_console + fi + + create_dns_record +} + +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$(cd "$(dirname "${script}")" && pwd)" + +source ${scriptDir}/common.sh +source ${scriptDir}/utility.sh +source ${scriptDir}/createDnsRecord.sh + +aksClusterRGName=$1 +aksClusterName=$2 +wlsDomainUID=$3 +subID=$4 +curRGName=$5 +appgwName=$6 +vnetName=$7 +appgwForAdminServer=$8 +enableCustomDNSAlias=$9 +dnsRGName=${10} +dnsZoneName=${11} +dnsAdminLabel=${12} +dnsClusterLabel=${13} +appgwAlias=${14} +appgwFrontendSSLCertData=${15} +appgwCertificateOption=${16} +enableCustomSSL=${17} +enableCookieBasedAffinity=${18} +enableRemoteConsole=${19} + +adminServerName=${constAdminServerName} # define in common.sh +appgwIngressHelmRepo="https://appgwingress.blob.core.windows.net/ingress-azure-helm-package/" +appgwFrontCertFileName="appgw-frontend-cert.pfx" +appgwFrontCertKeyDecrytedFileName="appgw-frontend-cert.key" +appgwFrontCertKeyFileName="appgw-frontend-cert-decryted.key" +appgwFrontPublicCertFileName="appgw-frontend-cert.crt" +appgwFrontendSecretName="frontend-tls" +appgwBackendSecretName="backend-tls" +appgwSelfsignedCert="generateCert" +azureAppgwIngressVersion="1.4.0" +clusterName=${constClusterName} +httpsListenerName="myHttpsListenerName$(date +%s)" +httpsRuleName="myHttpsRule$(date +%s)" +svcAdminServer="${wlsDomainUID}-${adminServerName}" +svcCluster="${wlsDomainUID}-cluster-${clusterName}" +wlsDomainNS="${wlsDomainUID}-ns" + +read_sensitive_parameters_from_stdin + +create_gateway_ingress diff --git a/weblogic-azure-aks/src/main/arm/scripts/createDnsRecord.sh b/weblogic-azure-aks/src/main/arm/scripts/createDnsRecord.sh new file mode 100644 index 000000000..61492c9d7 --- /dev/null +++ b/weblogic-azure-aks/src/main/arm/scripts/createDnsRecord.sh @@ -0,0 +1,62 @@ +# Copyright (c) 2021, Oracle Corporation and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# Description: to create DNS record in an existing DNS Zone. + +echo "Script ${0} starts" + +# Initialize +export script="${BASH_SOURCE[0]}" +export scriptDir="$(cd "$(dirname "${script}")" && pwd)" + +source ${scriptDir}/utility.sh + +# create dns alias for lb service +# $1: ipv4 address +# $2: label of subdomain +# $3: resource group name that has the DNS Zone. +# $4: DNS Zone name +function create_dns_A_record() { + ipv4Addr=$1 + label=$2 + dnsRGName=$3 + dnsZoneName=$4 + + az network dns record-set a add-record --ipv4-address ${ipv4Addr} \ + --record-set-name ${label} \ + --resource-group ${dnsRGName} \ + --zone-name ${dnsZoneName} + + if [ $? != 0 ]; then + echo_stderr "Failed to create DNS record: ${label}.${dnsZoneName}, ipv4: ${ipv4Addr}" + exit 1 + fi +} + +# create dns alias for app gateway +# $1: ipv4 address +# $2: label of subdomain +# $3: resource group name that has the DNS Zone. +# $4: DNS Zone name +function create_dns_CNAME_record() { + cname=$1 + label=$2 + dnsRGName=$3 + dnsZoneName=$4 + + az network dns record-set cname create \ + -g ${dnsRGName} \ + -z ${dnsZoneName} \ + -n ${label} + + az network dns record-set cname set-record \ + -g ${dnsRGName} \ + -z ${dnsZoneName} \ + --cname ${cname} \ + --record-set-name ${label} + + if [ $? != 0 ]; then + echo_stderr "Failed to create DNS record: ${label}.${dnsZoneName}, cname: ${cname}" + exit 1 + fi +} diff --git a/weblogic-azure-aks/src/main/arm/scripts/createLbSvc.sh b/weblogic-azure-aks/src/main/arm/scripts/createLbSvc.sh new file mode 100644 index 000000000..b47ebd266 --- /dev/null +++ b/weblogic-azure-aks/src/main/arm/scripts/createLbSvc.sh @@ -0,0 +1,475 @@ +# Copyright (c) 2021, Oracle Corporation and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# Description: to create Load Balancer Service for the following targets. +# * [Optional] admin server default channel +# * [Optional] admin server T3 channel +# * [Optional] cluster default channel +# * [Optional] cluster T3 channel +# +# Special parameter example: +# * lbSvcValues: [{"colName":"admin-t3","colTarget":"adminServerT3","colPort":"7005"},{"colName":"cluster","colTarget":"cluster1T3","colPort":"8011"}] + +echo "Script ${0} starts" + +function generate_admin_lb_definicion() { + cat <${scriptDir}/admin-server-lb.yaml +apiVersion: v1 +kind: Service +metadata: + name: ${adminServerLBSVCName} + namespace: ${wlsDomainNS} +EOF + + # to create internal load balancer service + if [[ "${enableInternalLB,,}" == "true" ]]; then + cat <>${scriptDir}/admin-server-lb.yaml + annotations: + service.beta.kubernetes.io/azure-load-balancer-internal: "true" +EOF + fi + + cat <>${scriptDir}/admin-server-lb.yaml +spec: + ports: + - name: default + port: ${adminLBPort} + protocol: TCP + targetPort: ${adminTargetPort} + selector: + weblogic.domainUID: ${wlsDomainUID} + weblogic.serverName: ${adminServerName} + sessionAffinity: None + type: LoadBalancer +EOF +} + +function generate_admin_t3_lb_definicion() { + cat <${adminServerT3LBDefinitionPath} +apiVersion: v1 +kind: Service +metadata: + name: ${adminServerT3LBSVCName} + namespace: ${wlsDomainNS} +EOF + + # to create internal load balancer service + if [[ "${enableInternalLB,,}" == "true" ]]; then + cat <>${adminServerT3LBDefinitionPath} + annotations: + service.beta.kubernetes.io/azure-load-balancer-internal: "true" +EOF + fi + + cat <>${adminServerT3LBDefinitionPath} +spec: + ports: + - name: default + port: ${adminT3LBPort} + protocol: TCP + targetPort: ${adminT3Port} + selector: + weblogic.domainUID: ${wlsDomainUID} + weblogic.serverName: ${adminServerName} + sessionAffinity: None + type: LoadBalancer +EOF +} + +function generate_cluster_lb_definicion() { + cat <${scriptDir}/cluster-lb.yaml +apiVersion: v1 +kind: Service +metadata: + name: ${clusterLBSVCName} + namespace: ${wlsDomainNS} +EOF + + # to create internal load balancer service + if [[ "${enableInternalLB,,}" == "true" ]]; then + cat <>${scriptDir}/cluster-lb.yaml + annotations: + service.beta.kubernetes.io/azure-load-balancer-internal: "true" +EOF + fi + + cat <>${scriptDir}/cluster-lb.yaml +spec: + ports: + - name: default + port: ${clusterLBPort} + protocol: TCP + targetPort: ${clusterTargetPort} + selector: + weblogic.domainUID: ${wlsDomainUID} + weblogic.clusterName: ${clusterName} + sessionAffinity: None + type: LoadBalancer +EOF +} + +function generate_cluster_t3_lb_definicion() { + cat <${clusterT3LBDefinitionPath} +apiVersion: v1 +kind: Service +metadata: + name: ${clusterT3LBSVCName} + namespace: ${wlsDomainNS} +EOF + + # to create internal load balancer service + if [[ "${enableInternalLB,,}" == "true" ]]; then + cat <>${clusterT3LBDefinitionPath} + annotations: + service.beta.kubernetes.io/azure-load-balancer-internal: "true" +EOF + fi + + cat <>${clusterT3LBDefinitionPath} +spec: + ports: + - name: default + port: ${clusterT3LBPort} + protocol: TCP + targetPort: ${clusterT3Port} + selector: + weblogic.domainUID: ${wlsDomainUID} + weblogic.clusterName: ${clusterName} + sessionAffinity: None + type: LoadBalancer +EOF +} + +function query_admin_target_port() { + if [[ "${enableCustomSSL,,}" == "true" ]]; then + adminTargetPort=$(utility_query_service_port ${svcAdminServer} ${wlsDomainNS} 'default-secure') + else + adminTargetPort=$(utility_query_service_port ${svcAdminServer} ${wlsDomainNS} 'default') + fi + + echo "Admin port of ${adminServerName}: ${adminTargetPort}" +} + +function query_cluster_target_port() { + if [[ "${enableCustomSSL,,}" == "true" ]]; then + clusterTargetPort=$(utility_query_service_port ${svcCluster} ${wlsDomainNS} 'default-secure') + else + clusterTargetPort=$(utility_query_service_port ${svcCluster} ${wlsDomainNS} 'default') + fi + + echo "Cluster port of ${clusterName}: ${clusterTargetPort}" +} + +function create_lb_svc_for_admin_server_default_channel() { + item=$1 # input values + + echo ${item} + + adminServerLBSVCNamePrefix=$(cut -d',' -f1 <<<$item) + adminServerLBSVCName="${adminServerLBSVCNamePrefix}-svc-lb-admin" + adminLBPort=$(cut -d',' -f3 <<<$item) + + generate_admin_lb_definicion + + kubectl apply -f ${scriptDir}/admin-server-lb.yaml + utility_validate_status "create lb service for admin server" + utility_waitfor_lb_svc_completed ${adminServerLBSVCName} \ + ${wlsDomainNS} \ + ${checkSVCStateMaxAttempt} \ + ${checkSVCInterval} + + adminServerEndpoint=$(kubectl get svc ${adminServerLBSVCName} -n ${wlsDomainNS} \ + -o=jsonpath='{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}') + adminConsoleEndpoint="${adminServerEndpoint}/console" + + if [ "${enableCustomDNSAlias,,}" == "true" ]; then + create_dns_A_record "${adminServerEndpoint%%:*}" ${dnsAdminLabel} ${dnsRGName} ${dnsZoneName} + adminConsoleEndpoint="${dnsAdminLabel}.${dnsZoneName}:${adminServerEndpoint#*:}/console" + fi +} + +function create_lb_svc_for_admin_t3_channel() { + item=$1 # input values + + adminServerT3LBSVCNamePrefix=$(cut -d',' -f1 <<<$item) + adminServerT3LBSVCName="${adminServerT3LBSVCNamePrefix}-svc-t3-lb-admin" + adminT3LBPort=$(cut -d',' -f3 <<<$item) + + adminServerT3LBDefinitionPath=${scriptDir}/admin-server-t3-lb.yaml + generate_admin_t3_lb_definicion + + kubectl apply -f ${adminServerT3LBDefinitionPath} + utility_validate_status "create lb service for admin server t3 channel" + utility_waitfor_lb_svc_completed ${adminServerT3LBSVCName} \ + ${wlsDomainNS} \ + ${checkSVCStateMaxAttempt} \ + ${checkSVCInterval} + + adminServerT3Endpoint=$(kubectl get svc ${adminServerT3LBSVCName} -n ${wlsDomainNS} \ + -o=jsonpath='{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}') + + if [ "${enableCustomDNSAlias,,}" == "true" ]; then + create_dns_A_record "${adminServerT3Endpoint%%:*}" "${dnszoneAdminT3ChannelLabel}" ${dnsRGName} ${dnsZoneName} + adminServerT3Endpoint="${dnszoneAdminT3ChannelLabel}.${dnsZoneName}:${adminServerT3Endpoint#*:}" + fi +} + +function create_lb_svc_for_cluster_default_channel() { + item=$1 # input values + + clusterLBSVCNamePrefix=$(cut -d',' -f1 <<<$item) + clusterLBSVCName="${clusterLBSVCNamePrefix}-svc-lb-cluster" + clusterLBPort=$(cut -d',' -f3 <<<$item) + + generate_cluster_lb_definicion + + kubectl apply -f ${scriptDir}/cluster-lb.yaml + utility_validate_status "create lb service for cluster" + utility_waitfor_lb_svc_completed ${clusterLBSVCName} \ + ${wlsDomainNS} \ + ${checkSVCStateMaxAttempt} \ + ${checkSVCInterval} + + clusterEndpoint=$(kubectl get svc ${clusterLBSVCName} -n ${wlsDomainNS} -o=jsonpath='{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}') + + if [ "${enableCustomDNSAlias,,}" == "true" ]; then + create_dns_A_record "${clusterEndpoint%%:*}" ${dnsClusterLabel} ${dnsRGName} ${dnsZoneName} + clusterEndpoint="${dnsClusterLabel}.${dnsZoneName}:${clusterEndpoint#*:}/" + fi +} + +function create_lb_svc_for_cluster_t3_channel() { + item=$1 # input values + + clusterT3LBSVCNamePrefix=$(cut -d',' -f1 <<<$item) + clusterT3LBSVCName="${clusterT3LBSVCNamePrefix}-svc-lb-cluster" + clusterT3LBPort=$(cut -d',' -f3 <<<$item) + + clusterT3LBDefinitionPath=${scriptDir}/cluster-t3-lb.yaml + generate_cluster_t3_lb_definicion + + kubectl apply -f ${clusterT3LBDefinitionPath} + utility_validate_status "create lb service for cluster t3 channel" + utility_waitfor_lb_svc_completed ${clusterT3LBSVCName} \ + ${wlsDomainNS} \ + ${checkSVCStateMaxAttempt} \ + ${checkSVCInterval} + + clusterT3Endpoint=$(kubectl get svc ${clusterT3LBSVCName} -n ${wlsDomainNS} \ + -o=jsonpath='{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}') + + if [ "${enableCustomDNSAlias,,}" == "true" ]; then + create_dns_A_record "${clusterT3Endpoint%%:*}" ${dnszoneClusterT3ChannelLabel} ${dnsRGName} ${dnsZoneName} + clusterT3Endpoint="${dnszoneClusterT3ChannelLabel}.${dnsZoneName}:${clusterT3Endpoint#*:}" + fi +} + +function patch_admin_t3_public_address() { + # patch admin t3 public address + if [ "${enableCustomDNSAlias,,}" == "true" ]; then + adminT3Address="${dnszoneAdminT3ChannelLabel}.${dnsZoneName}" + else + adminT3Address=$(kubectl -n ${wlsDomainNS} get svc ${adminServerT3LBSVCName} -o json | + jq '. | .status.loadBalancer.ingress[0].ip' | + tr -d "\"") + fi + + if [ $? == 1 ]; then + echo_stderr "Failed to query public IP of admin t3 channel." + fi + + currentDomainConfig=$(echo ${currentDomainConfig} | + jq \ + --arg match "${constAdminT3AddressEnvName}" \ + --arg replace "${adminT3Address}" \ + '.spec.serverPod.env |= map(if .name==$match then (.value=$replace) else . end)') +} + +function patch_cluster_t3_public_address() { + #patch cluster t3 pubilc address + if [ "${enableCustomDNSAlias,,}" == "true" ]; then + clusterT3Adress="${dnszoneClusterT3ChannelLabel}.${dnsZoneName}" + else + clusterT3Adress=$(kubectl -n ${wlsDomainNS} get svc ${clusterT3LBSVCName} -o json | + jq '. | .status.loadBalancer.ingress[0].ip' | + tr -d "\"") + fi + + if [ $? == 1 ]; then + echo_stderr "Failed to query public IP of cluster t3 channel." + fi + + currentDomainConfig=$(echo ${currentDomainConfig} | + jq \ + --arg match "${constClusterT3AddressEnvName}" \ + --arg replace "${clusterT3Adress}" \ + '.spec.serverPod.env |= map(if .name==$match then (.value=$replace) else . end)') +} + +function rolling_update_with_t3_public_address() { + timestampBeforePatchingDomain=$(date +%s) + currentDomainConfig=$(kubectl -n ${wlsDomainNS} get domain ${wlsDomainUID} -o json) + cat <${scriptDir}/domainPreviousConfiguration.yaml +${currentDomainConfig} +EOF + + # update public address of t3 channel + if [[ "${enableAdminT3Channel,,}" == "true" ]]; then + patch_admin_t3_public_address + fi + + if [[ "${enableClusterT3Channel,,}" == "true" ]]; then + patch_cluster_t3_public_address + fi + + if [[ "${enableClusterT3Channel,,}" == "true" ]] || [[ "${enableAdminT3Channel,,}" == "true" ]]; then + # restart cluster + restartVersion=$(kubectl -n ${wlsDomainNS} get domain ${wlsDomainUID} -o json | + jq '. | .spec.restartVersion' | + tr -d "\"") + restartVersion=$((restartVersion + 1)) + + currentDomainConfig=$(echo ${currentDomainConfig} | + jq \ + --arg version "${restartVersion}" \ + '.spec.restartVersion |= $version') + + echo "rolling restart the cluster with t3 public address." + # echo the configuration for debugging + cat <${scriptDir}/domainNewConfiguration.yaml +${currentDomainConfig} +EOF + echo ${currentDomainConfig} | kubectl -n ${wlsDomainNS} apply -f - + + replicas=$(kubectl -n ${wlsDomainNS} get domain ${wlsDomainUID} -o json | + jq '. | .spec.clusters[] | .replicas') + + # wait for the restart completed. + utility_wait_for_pod_restarted \ + ${timestampBeforePatchingDomain} \ + ${replicas} \ + ${wlsDomainUID} \ + ${checkPodStatusMaxAttemps} \ + ${checkPodStatusInterval} + + utility_wait_for_pod_completed \ + ${replicas} \ + ${wlsDomainNS} \ + ${checkPodStatusMaxAttemps} \ + ${checkPodStatusInterval} + fi +} + +#Output value to deployment scripts +function output_result() { + echo ${adminConsoleEndpoint} + echo ${clusterEndpoint} + echo ${adminServerT3Endpoint} + echo ${clusterT3Endpoint} + + result=$(jq -n -c \ + --arg adminEndpoint $adminConsoleEndpoint \ + --arg clusterEndpoint $clusterEndpoint \ + --arg adminT3Endpoint $adminServerT3Endpoint \ + --arg clusterT3Endpoint $clusterT3Endpoint \ + '{adminConsoleEndpoint: $adminEndpoint, clusterEndpoint: $clusterEndpoint, adminServerT3Endpoint: $adminT3Endpoint, clusterT3Endpoint: $clusterT3Endpoint}') + echo "result is: $result" + echo $result >$AZ_SCRIPTS_OUTPUT_PATH +} + +function create_svc_lb() { + query_admin_target_port + query_cluster_target_port + + # Parse lb svc input values + # Generate valid json + ret=$(echo $lbSvcValues | sed "s/\:/\\\"\:\\\"/g" | + sed "s/{/{\"/g" | + sed "s/}/\"}/g" | + sed "s/,/\",\"/g" | + sed "s/}\",\"{/},{/g" | + tr -d \(\)) + + cat <${scriptDir}/lbConfiguration.json +${ret} +EOF + + array=$(jq -r '.[] | "\(.colName),\(.colTarget),\(.colPort)"' ${scriptDir}/lbConfiguration.json) + for item in $array; do + # LB config for admin-server + target=$(cut -d',' -f2 <<<$item) + if [[ "${target}" == "adminServer" ]]; then + create_lb_svc_for_admin_server_default_channel ${item} + elif [[ "${target}" == "cluster1" ]]; then + create_lb_svc_for_cluster_default_channel ${item} + elif [[ "${target}" == "adminServerT3" ]]; then + echo "query admin t3 port" + adminT3Port=$(utility_query_service_port ${svcAdminServer} ${wlsDomainNS} 't3channel') + adminT3sPort=$(utility_query_service_port ${svcAdminServer} ${wlsDomainNS} 't3schannel') + + if [[ "${adminT3Port}" == "null" ]] && [[ "${adminT3sPort}" == "null" ]]; then + continue + fi + + if [[ "${adminT3sPort}" != "null" ]]; then + adminT3Port=${adminT3sPort} + fi + + create_lb_svc_for_admin_t3_channel $item + enableAdminT3Channel=true + elif [[ "${target}" == "cluster1T3" ]]; then + echo "query cluster t3 port" + clusterT3Port=$(utility_query_service_port ${svcCluster} ${wlsDomainNS} 't3channel') + clusterT3sPort=$(utility_query_service_port ${svcCluster} ${wlsDomainNS} 't3schannel') + + if [[ "${clusterT3Port}" == "null" ]] && [[ "${clusterT3sPort}" == "null" ]]; then + continue + fi + + if [[ "${clusterT3sPort}" != "null" ]]; then + clusterT3Port=${clusterT3sPort} + fi + + create_lb_svc_for_cluster_t3_channel ${item} + enableClusterT3Channel=true + fi + done + + rolling_update_with_t3_public_address +} + +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$(cd "$(dirname "${script}")" && pwd)" + +source ${scriptDir}/common.sh +source ${scriptDir}/utility.sh +source ${scriptDir}/createDnsRecord.sh + +enableInternalLB=$1 +enableCustomSSL=$2 +enableCustomDNSAlias=$3 +dnsRGName=$4 +dnsZoneName=$5 +dnsAdminLabel=$6 +dnszoneAdminT3ChannelLabel=$7 +dnsClusterLabel=$8 +dnszoneClusterT3ChannelLabel=$9 +lbSvcValues=${10} +wlsDomainUID=${11} + +adminConsoleEndpoint="null" +adminServerName=${constAdminServerName} # define in common.sh +adminServerT3Endpoint="null" +clusterEndpoint="null" +clusterName=${constClusterName} +clusterT3Endpoint="null" +svcAdminServer="${wlsDomainUID}-${adminServerName}" +svcCluster="${wlsDomainUID}-cluster-${clusterName}" +wlsDomainNS="${wlsDomainUID}-ns" + +echo ${lbSvcValues} + +create_svc_lb + +output_result diff --git a/weblogic-azure-aks/src/main/arm/scripts/createVMAndBuildImage.sh b/weblogic-azure-aks/src/main/arm/scripts/createVMAndBuildImage.sh index cc06553c3..51aa393db 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/createVMAndBuildImage.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/createVMAndBuildImage.sh @@ -94,7 +94,7 @@ function build_docker_image() { --publisher Microsoft.Azure.Extensions \ --version 2.0 \ --settings "{ \"fileUris\": [\"${scriptURL}model.properties\",\"${scriptURL}genImageModel.sh\",\"${scriptURL}buildWLSDockerImage.sh\",\"${scriptURL}common.sh\"]}" \ - --protected-settings "{\"commandToExecute\":\"echo ${azureACRPassword} ${ocrSSOPSW} | bash buildWLSDockerImage.sh ${wlsImagePath} ${azureACRServer} ${azureACRUserName} ${newImageTag} \\\"${appPackageUrls}\\\" ${ocrSSOUser} ${wlsClusterSize} ${enableCustomSSL} \"}" + --protected-settings "{\"commandToExecute\":\"echo ${azureACRPassword} ${ocrSSOPSW} | bash buildWLSDockerImage.sh ${wlsImagePath} ${azureACRServer} ${azureACRUserName} ${newImageTag} \\\"${appPackageUrls}\\\" ${ocrSSOUser} ${wlsClusterSize} ${enableCustomSSL} ${enableAdminT3Tunneling} ${enableClusterT3Tunneling} \"}" cleanup_vm } @@ -102,6 +102,12 @@ function build_docker_image() { # Shell Global settings set -e #Exit immediately if a command exits with a non-zero status. +# Main script +export script="${BASH_SOURCE[0]}" +export scriptDir="$(cd "$(dirname "${script}")" && pwd)" + +source ${scriptDir}/common.sh + export currentResourceGroup=$1 export wlsImageTag=$2 export azureACRServer=$3 @@ -112,6 +118,8 @@ export ocrSSOUser=$7 export wlsClusterSize=$8 export enableCustomSSL=$9 export scriptURL=${10} +export enableAdminT3Tunneling=${11} +export enableClusterT3Tunneling=${12} read_sensitive_parameters_from_stdin diff --git a/weblogic-azure-aks/src/main/arm/scripts/genDomainConfig.sh b/weblogic-azure-aks/src/main/arm/scripts/genDomainConfig.sh index 2f9e716b8..d4072b1d4 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/genDomainConfig.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/genDomainConfig.sh @@ -14,7 +14,15 @@ export wlsMemory=$7 export wlsManagedPrefix=$8 export enableSSL=${9} export enablePV=${10} -export javaOptions=${11} +export enableAdminT3Tunneling=${11} +export enableClusterT3Tunneling=${12} +export t3AdminPort=${13} +export t3ClusterPort=${14} +export clusterName=${15} +export javaOptions=${16} + +export adminServiceUrl="${wlsDomainUID}-admin-server.${wlsDomainUID}-ns.svc.cluster.local" +export clusterServiceUrl="${wlsDomainUID}-cluster-${clusterName}.${wlsDomainUID}-ns.svc.cluster.local" cat <$filePath # Copyright (c) 2021, Oracle Corporation and/or its affiliates. @@ -86,7 +94,8 @@ spec: - name: MANAGED_SERVER_PREFIX value: "${wlsManagedPrefix}" EOF - if [[ "${enableSSL,,}" == "true" ]]; then + +if [[ "${enableSSL,,}" == "true" ]]; then cat <>$filePath - name: SSL_IDENTITY_PRIVATE_KEY_ALIAS valueFrom: @@ -131,15 +140,33 @@ EOF EOF fi - # Resources - cat <>$filePath +if [[ "${enableAdminT3Tunneling,,}" == "true" ]]; then + cat <>$filePath + - name: T3_TUNNELING_ADMIN_PORT + value: "${t3AdminPort}" + - name: T3_TUNNELING_ADMIN_ADDRESS + value: "${adminServiceUrl}" +EOF +fi + +if [[ "${enableClusterT3Tunneling,,}" == "true" ]]; then + cat <>$filePath + - name: T3_TUNNELING_CLUSTER_PORT + value: "${t3ClusterPort}" + - name: T3_TUNNELING_CLUSTER_ADDRESS + value: "${clusterServiceUrl}" +EOF +fi + +# Resources +cat <>$filePath resources: requests: cpu: "${wlsCPU}" memory: "${wlsMemory}" EOF - if [[ "${enablePV,,}" == "true" ]]; then +if [[ "${enablePV,,}" == "true" ]]; then cat <>$filePath # Optional volumes and mounts for the domain's pods. See also 'logHome'. volumes: @@ -150,9 +177,9 @@ EOF - mountPath: /shared name: ${wlsDomainUID}-pv-azurefile EOF - fi +fi - cat <>$filePath +cat <>$filePath # The desired behavior for starting the domain's administration server. adminServer: # The serverStartState legal values are "RUNNING" or "ADMIN" diff --git a/weblogic-azure-aks/src/main/arm/scripts/genImageModel.sh b/weblogic-azure-aks/src/main/arm/scripts/genImageModel.sh index 4d07a234e..8b5c3d818 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/genImageModel.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/genImageModel.sh @@ -10,6 +10,17 @@ source ${scriptDir}/common.sh export filePath=$1 export appPackageUrls=$2 export enableCustomSSL=$3 +export enableAdminT3Tunneling=$4 +export enableClusterT3Tunneling=$5 + +export enableT3s=${enableCustomSSL,,} +export t3Protocol="t3" +export t3ChannelName="T3Channel" + +if [ "${enableCustomSSL,,}" == "true" ]; then + t3Protocol="t3s" + t3ChannelName="T3sChannel" +fi cat <${filePath} # Copyright (c) 2020, 2021, Oracle and/or its affiliates. @@ -42,7 +53,24 @@ topology: ListenPort: 7001 EOF -if [[ "${enableCustomSSL,,}" == "true" ]];then +if [[ "${enableAdminT3Tunneling,,}" == "true" ]];then + cat <>${filePath} + NetworkAccessPoint: + ${t3ChannelName}: + Protocol: '${t3Protocol}' + ListenPort: "@@ENV:T3_TUNNELING_ADMIN_PORT@@" + PublicPort: "@@ENV:T3_TUNNELING_ADMIN_PORT@@" + HttpEnabledForThisProtocol: true + OutboundEnabled: false + Enabled: true + TwoWaySSLEnabled: ${enableT3s} + ClientCertificateEnforced: false + TunnelingEnabled: true + PublicAddress: '@@ENV:T3_TUNNELING_ADMIN_ADDRESS@@' +EOF +fi + +if [[ "${enableCustomSSL,,}" == "true" ]]; then cat <>${filePath} SSL: HostnameVerificationIgnored: true @@ -68,6 +96,23 @@ cat <>${filePath} ListenPort: 8001 EOF +if [[ "${enableClusterT3Tunneling,,}" == "true" ]];then + cat <>${filePath} + NetworkAccessPoint: + ${t3ChannelName}: + Protocol: '${t3Protocol}' + ListenPort: "@@ENV:T3_TUNNELING_CLUSTER_PORT@@" + PublicPort: "@@ENV:T3_TUNNELING_CLUSTER_PORT@@" + HttpEnabledForThisProtocol: true + OutboundEnabled: false + Enabled: true + TwoWaySSLEnabled: ${enableT3s} + ClientCertificateEnforced: false + TunnelingEnabled: true + PublicAddress: '@@ENV:T3_TUNNELING_CLUSTER_ADDRESS@@' +EOF +fi + if [[ "${enableCustomSSL,,}" == "true" ]];then cat <>${filePath} SSL: @@ -142,4 +187,7 @@ EOF Target: 'cluster-1' EOF index=$((index + 1)) - done \ No newline at end of file + done + +# print model +cat ${filePath} \ No newline at end of file diff --git a/weblogic-azure-aks/src/main/arm/scripts/invokeSetupNetworking.sh b/weblogic-azure-aks/src/main/arm/scripts/invokeSetupNetworking.sh index 0e87e661b..32edb91ad 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/invokeSetupNetworking.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/invokeSetupNetworking.sh @@ -32,6 +32,8 @@ Usage: + + END ) echo_stdout "${usage}" @@ -72,6 +74,8 @@ export appgwCertificateOption=${22} export enableCustomSSL=${23} export enableCookieBasedAffinity=${24} export enableRemoteConsole=${25} +export dnszoneAdminT3ChannelLabel=${26} +export dnszoneClusterT3ChannelLabel=${27} echo ${spBase64String} \ ${appgwFrontendSSLCertPsw} | \ @@ -98,7 +102,9 @@ echo ${spBase64String} \ ${appgwCertificateOption} \ ${enableCustomSSL} \ ${enableCookieBasedAffinity} \ - ${enableRemoteConsole} + ${enableRemoteConsole} \ + ${dnszoneAdminT3ChannelLabel} \ + ${dnszoneClusterT3ChannelLabel} if [ $? -ne 0 ]; then usage 1 diff --git a/weblogic-azure-aks/src/main/arm/scripts/invokeSetupWLSDomain.sh b/weblogic-azure-aks/src/main/arm/scripts/invokeSetupWLSDomain.sh index 1a5bf0cc7..22d559a25 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/invokeSetupWLSDomain.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/invokeSetupWLSDomain.sh @@ -37,6 +37,11 @@ Usage: + + + + + END ) echo_stdout "${usage}" @@ -82,6 +87,11 @@ export wlsTrustData=${27} wlsTrustPsw=${28} export wlsTrustType=${29} export enablePV=${30} +export enableAdminT3Tunneling=${31} +export enableClusterT3Tunneling=${32} +export t3AdminPort=${33} +export t3ClusterPort=${34} +export wlsJavaOption=${35} echo ${ocrSSOPSW} \ ${wlsPassword} \ @@ -113,7 +123,12 @@ echo ${ocrSSOPSW} \ ${wlsIdentityAlias} \ ${wlsTrustData} \ ${wlsTrustType} \ - ${enablePV} + ${enablePV} \ + ${enableAdminT3Tunneling} \ + ${enableClusterT3Tunneling} \ + ${t3AdminPort} \ + ${t3ClusterPort} \ + ${wlsJavaOption} if [ $? -ne 0 ]; then usage 1 diff --git a/weblogic-azure-aks/src/main/arm/scripts/setupNetworking.sh b/weblogic-azure-aks/src/main/arm/scripts/setupNetworking.sh index 8c504fb25..0fb9500e7 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/setupNetworking.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/setupNetworking.sh @@ -5,24 +5,7 @@ echo "Script ${0} starts" # read from stdin function read_sensitive_parameters_from_stdin() { - read spBase64String appgwFrontendSSLCertPsw -} - -function install_helm() { - # Install Helm - browserURL=$(curl -m ${curlMaxTime} -s https://api.github.com/repos/helm/helm/releases/latest | - grep "browser_download_url.*linux-amd64.tar.gz.asc" | - cut -d : -f 2,3 | - tr -d \") - helmLatestVersion=${browserURL#*download\/} - helmLatestVersion=${helmLatestVersion%%\/helm*} - helmPackageName=helm-${helmLatestVersion}-linux-amd64.tar.gz - curl -m ${curlMaxTime} -fL https://get.helm.sh/${helmPackageName} -o /tmp/${helmPackageName} - tar -zxvf /tmp/${helmPackageName} -C /tmp - mv /tmp/linux-amd64/helm /usr/local/bin/helm - echo "Helm version" - helm version - validate_status "Finished installing Helm." + read spBase64String appgwFrontendSSLCertPsw } # Install latest kubectl and Helm @@ -35,28 +18,13 @@ function install_utilities() { cd apps # Install kubectl - az aks install-cli - echo "kubectl version" - ret=$(kubectl --help) - validate_status ${ret} -} - -#Output value to deployment scripts -function output_result() { - echo ${adminConsoleEndpoint} - echo ${clusterEndpoint} - - result=$(jq -n -c \ - --arg adminEndpoint $adminConsoleEndpoint \ - --arg clusterEndpoint $clusterEndpoint \ - '{adminConsoleEndpoint: $adminEndpoint, clusterEndpoint: $clusterEndpoint}') - echo "result is: $result" - echo $result >$AZ_SCRIPTS_OUTPUT_PATH + install_kubectl } #Function to display usage message function usage() { - usage=$(cat <<-END + usage=$( + cat <<-END Usage: echo | ./setupNetworking.sh @@ -83,45 +51,17 @@ echo | + + END -) - echo_stdout ${usage} - if [ $1 -eq 1 ]; then - echo_stderr ${usage} - exit 1 - fi -} - -#Validate teminal status with $?, exit with exception if errors happen. -function validate_status() { - if [ $? == 1 ]; then - echo_stderr "$@" - echo_stderr "Errors happen, exit 1." + ) + echo_stdout ${usage} + if [ $1 -eq 1 ]; then + echo_stderr ${usage} exit 1 - else - echo_stdout "$@" fi } -function waitfor_svc_completed() { - svcName=$1 - - attempts=0 - svcState="running" - while [ ! "$svcState" == "completed" ] && [ $attempts -lt ${perfSVCAttemps} ]; do - svcState="completed" - attempts=$((attempts + 1)) - echo Waiting for job completed...${attempts} - sleep ${perfRetryInterval} - - ret=$(kubectl get svc ${svcName} -n ${wlsDomainNS} | - grep -c "Running") - if [ -z "${ret}" ]; then - svcState="running" - fi - done -} - #Function to validate input function validate_input() { if [[ -z "$aksClusterRGName" || -z "${aksClusterName}" ]]; then @@ -223,449 +163,16 @@ function validate_input() { echo_stderr "enableRemoteConsole is required. " usage 1 fi -} - -function generate_admin_lb_definicion() { - cat <${scriptDir}/admin-server-lb.yaml -apiVersion: v1 -kind: Service -metadata: - name: ${adminServerLBSVCName} - namespace: ${wlsDomainNS} -EOF - - # to create internal load balancer service - if [[ "${enableInternalLB,,}" == "true" ]]; then - cat <>${scriptDir}/admin-server-lb.yaml - annotations: - service.beta.kubernetes.io/azure-load-balancer-internal: "true" -EOF - fi - - cat <>${scriptDir}/admin-server-lb.yaml -spec: - ports: - - name: default - port: ${adminLBPort} - protocol: TCP - targetPort: ${adminTargetPort} - selector: - weblogic.domainUID: ${wlsDomainUID} - weblogic.serverName: ${adminServerName} - sessionAffinity: None - type: LoadBalancer -EOF -} - -function generate_cluster_lb_definicion() { - cat <${scriptDir}/cluster-lb.yaml -apiVersion: v1 -kind: Service -metadata: - name: ${clusterLBSVCName} - namespace: ${wlsDomainNS} -EOF - - # to create internal load balancer service - if [[ "${enableInternalLB,,}" == "true" ]]; then - cat <>${scriptDir}/cluster-lb.yaml - annotations: - service.beta.kubernetes.io/azure-load-balancer-internal: "true" -EOF - fi - - cat <>${scriptDir}/cluster-lb.yaml -spec: - ports: - - name: default - port: ${clusterLBPort} - protocol: TCP - targetPort: ${clusterTargetPort} - selector: - weblogic.domainUID: ${wlsDomainUID} - weblogic.clusterName: ${clusterName} - sessionAffinity: None - type: LoadBalancer -EOF -} - -function generate_appgw_cluster_config_file_expose_https() -{ - export clusterIngressHttpsName=${wlsDomainUID}-cluster-appgw-ingress-https-svc - export clusterAppgwIngressHttpsYamlPath=${scriptDir}/appgw-cluster-ingress-https-svc.yaml - cat <${clusterAppgwIngressHttpsYamlPath} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: ${clusterIngressHttpsName} - namespace: ${wlsDomainNS} - annotations: - kubernetes.io/ingress.class: azure/application-gateway -EOF - -if [[ "${enableCookieBasedAffinity,,}" == "true" ]];then - cat <>${clusterAppgwIngressHttpsYamlPath} - appgw.ingress.kubernetes.io/cookie-based-affinity: "true" -EOF -fi - -cat <>${clusterAppgwIngressHttpsYamlPath} -spec: - tls: - - secretName: ${appgwFrontendSecretName} - rules: - - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: ${svcCluster} - port: - number: ${clusterTargetPort} -EOF -} - -function generate_appgw_cluster_config_file_nossl() -{ - export clusterIngressName=${wlsDomainUID}-cluster-appgw-ingress-svc - export clusterAppgwIngressYamlPath=${scriptDir}/appgw-cluster-ingress-svc.yaml - cat <${clusterAppgwIngressYamlPath} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: ${clusterIngressName} - namespace: ${wlsDomainNS} - annotations: - kubernetes.io/ingress.class: azure/application-gateway -EOF - -if [[ "${enableCookieBasedAffinity,,}" == "true" ]];then - cat <>${clusterAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/cookie-based-affinity: "true" -EOF -fi - -cat <>${clusterAppgwIngressYamlPath} -spec: - rules: - - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: ${svcCluster} - port: - number: ${clusterTargetPort} -EOF -} - -function generate_appgw_cluster_config_file_ssl() -{ - export clusterIngressName=${wlsDomainUID}-cluster-appgw-ingress-svc - export clusterAppgwIngressYamlPath=${scriptDir}/appgw-cluster-ingress-svc.yaml - cat <${clusterAppgwIngressYamlPath} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: ${clusterIngressName} - namespace: ${wlsDomainNS} - annotations: - kubernetes.io/ingress.class: azure/application-gateway - appgw.ingress.kubernetes.io/ssl-redirect: "true" - appgw.ingress.kubernetes.io/backend-protocol: "https" -EOF - if [[ "${enableCustomDNSAlias,,}" == "true" ]];then - cat <>${clusterAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/backend-hostname: "${dnsClusterLabel}.${dnsZoneName}" -EOF - else - cat <>${clusterAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/backend-hostname: "${appgwAlias}" -EOF - fi - - if [[ "${enableCookieBasedAffinity,,}" == "true" ]];then - cat <>${clusterAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/cookie-based-affinity: "true" -EOF -fi - -cat <>${clusterAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/appgw-trusted-root-certificate: "${appgwBackendSecretName}" - -spec: - tls: - - secretName: ${appgwFrontendSecretName} - rules: - - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: ${svcCluster} - port: - number: ${clusterTargetPort} -EOF -} - -function generate_appgw_admin_config_file_nossl() -{ - export adminIngressName=${wlsDomainUID}-admin-appgw-ingress-svc - export adminAppgwIngressYamlPath=${scriptDir}/appgw-admin-ingress-svc.yaml - cat <${adminAppgwIngressYamlPath} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: ${adminIngressName} - namespace: ${wlsDomainNS} - annotations: - kubernetes.io/ingress.class: azure/application-gateway -EOF - - if [[ "${enableCookieBasedAffinity,,}" == "true" ]];then - cat <>${adminAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/cookie-based-affinity: "true" -EOF -fi - -cat <>${adminAppgwIngressYamlPath} -spec: - rules: - - http: - paths: - - path: /console* - pathType: Prefix - backend: - service: - name: ${svcAdminServer} - port: - number: ${adminTargetPort} -EOF -} - -function generate_appgw_admin_remote_config_file_nossl() -{ - cat <${adminRemoteAppgwIngressYamlPath} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: ${adminRemoteIngressName} - namespace: ${wlsDomainNS} - annotations: - kubernetes.io/ingress.class: azure/application-gateway - appgw.ingress.kubernetes.io/backend-path-prefix: "/" -EOF - - if [[ "${enableCookieBasedAffinity,,}" == "true" ]];then - cat <>${adminRemoteAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/cookie-based-affinity: "true" -EOF -fi - -cat <>${adminRemoteAppgwIngressYamlPath} -spec: - rules: - - http: - paths: - - path: /remoteconsole* - pathType: Prefix - backend: - service: - name: ${svcAdminServer} - port: - number: ${adminTargetPort} -EOF -} - -function generate_appgw_admin_config_file_ssl() -{ - export adminIngressName=${wlsDomainUID}-admin-appgw-ingress-svc - export adminAppgwIngressYamlPath=${scriptDir}/appgw-admin-ingress-svc.yaml - cat <${adminAppgwIngressYamlPath} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: ${adminIngressName} - namespace: ${wlsDomainNS} - annotations: - kubernetes.io/ingress.class: azure/application-gateway - appgw.ingress.kubernetes.io/ssl-redirect: "true" - appgw.ingress.kubernetes.io/backend-protocol: "https" -EOF - - if [[ "${enableCustomDNSAlias,,}" == "true" ]];then - cat <>${adminAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/backend-hostname: "${dnsAdminLabel}.${dnsZoneName}" -EOF - else - cat <>${adminAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/backend-hostname: "${appgwAlias}" -EOF - fi - - if [[ "${enableCookieBasedAffinity,,}" == "true" ]];then - cat <>${adminAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/cookie-based-affinity: "true" -EOF -fi - - cat <>${adminAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/appgw-trusted-root-certificate: "${appgwBackendSecretName}" - -spec: - tls: - - secretName: ${appgwFrontendSecretName} - rules: - - http: - paths: - - path: /console* - pathType: Prefix - backend: - service: - name: ${svcAdminServer} - port: - number: ${adminTargetPort} -EOF -} - -function generate_appgw_admin_remote_config_file_ssl() -{ - cat <${adminRemoteAppgwIngressYamlPath} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: ${adminRemoteIngressName} - namespace: ${wlsDomainNS} - annotations: - kubernetes.io/ingress.class: azure/application-gateway - appgw.ingress.kubernetes.io/backend-path-prefix: "/" - appgw.ingress.kubernetes.io/ssl-redirect: "true" - appgw.ingress.kubernetes.io/backend-protocol: "https" - -EOF - - if [[ "${enableCustomDNSAlias,,}" == "true" ]];then - cat <>${adminRemoteAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/backend-hostname: "${dnsAdminLabel}.${dnsZoneName}" -EOF - else - cat <>${adminRemoteAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/backend-hostname: "${appgwAlias}" -EOF - fi - - if [[ "${enableCookieBasedAffinity,,}" == "true" ]];then - cat <>${adminRemoteAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/cookie-based-affinity: "true" -EOF -fi - - cat <>${adminRemoteAppgwIngressYamlPath} - appgw.ingress.kubernetes.io/appgw-trusted-root-certificate: "${appgwBackendSecretName}" - -spec: - tls: - - secretName: ${appgwFrontendSecretName} - rules: - - http: - paths: - - path: /remoteconsole* - pathType: Prefix - backend: - service: - name: ${svcAdminServer} - port: - number: ${adminTargetPort} -EOF -} - -function generate_appgw_cluster_config_file() { - if [[ "${enableCustomSSL,,}" == "true" ]];then - generate_appgw_cluster_config_file_ssl - else - generate_appgw_cluster_config_file_nossl - generate_appgw_cluster_config_file_expose_https - fi -} - -function generate_appgw_admin_config_file() { - if [[ "${enableCustomSSL,,}" == "true" ]];then - generate_appgw_admin_config_file_ssl - else - generate_appgw_admin_config_file_nossl - fi -} - -function generate_appgw_admin_remote_config_file() { - if [[ "${enableCustomSSL,,}" == "true" ]];then - generate_appgw_admin_remote_config_file_ssl - else - generate_appgw_admin_remote_config_file_nossl - fi -} - -function output_create_gateway_ssl_k8s_secret(){ - echo "export gateway frontend certificates" - echo "$appgwFrontendSSLCertData" | base64 -d >${scriptDir}/$appgwFrontCertFileName - - appgwFrontendSSLCertPassin=${appgwFrontendSSLCertPsw} - if [[ "$appgwCertificateOption" == "${appgwSelfsignedCert}" ]];then - appgwFrontendSSLCertPassin="" # empty password - fi - - openssl pkcs12 \ - -in ${scriptDir}/$appgwFrontCertFileName \ - -nocerts \ - -out ${scriptDir}/$appgwFrontCertKeyFileName \ - -passin pass:${appgwFrontendSSLCertPassin} \ - -passout pass:${appgwFrontendSSLCertPsw} - - validate_status "Export key from frontend certificate." - openssl rsa -in ${scriptDir}/$appgwFrontCertKeyFileName \ - -out ${scriptDir}/$appgwFrontCertKeyDecrytedFileName \ - -passin pass:${appgwFrontendSSLCertPsw} - - validate_status "Decryte private key." - - openssl pkcs12 \ - -in ${scriptDir}/$appgwFrontCertFileName \ - -clcerts \ - -nokeys \ - -out ${scriptDir}/$appgwFrontPublicCertFileName \ - -passin pass:${appgwFrontendSSLCertPassin} \ - - validate_status "Export cert from frontend certificate." - - echo "create k8s tsl secret for app gateway frontend ssl certificate" - kubectl -n ${wlsDomainNS} create secret tls ${appgwFrontendSecretName} \ - --key="${scriptDir}/$appgwFrontCertKeyDecrytedFileName" \ - --cert="${scriptDir}/$appgwFrontPublicCertFileName" -} - -function query_admin_target_port() { - if [[ "${enableCustomSSL,,}" == "true" ]];then - adminTargetPort=$(kubectl describe service ${svcAdminServer} -n ${wlsDomainNS} | grep 'default-secure' | tr -d -c 0-9) - else - adminTargetPort=$(kubectl describe service ${svcAdminServer} -n ${wlsDomainNS} | grep 'default' | tr -d -c 0-9) + if [ -z "$dnszoneAdminT3ChannelLabel" ]; then + echo_stderr "dnszoneAdminT3ChannelLabel is required. " + usage 1 fi - validate_status "Query admin target port." - echo "Target port of ${adminServerName}: ${adminTargetPort}" -} - -function query_cluster_target_port() { - if [[ "${enableCustomSSL,,}" == "true" ]];then - clusterTargetPort=$(kubectl describe service ${svcCluster} -n ${wlsDomainNS} | grep 'default-secure' | tr -d -c 0-9) - else - clusterTargetPort=$(kubectl describe service ${svcCluster} -n ${wlsDomainNS} | grep 'default' | tr -d -c 0-9) + if [ -z "$dnszoneClusterT3ChannelLabel" ]; then + echo_stderr "dnszoneClusterT3ChannelLabel is required. " + usage 1 fi - - validate_status "Query cluster 1 target port." - echo "Target port of ${clusterName}: ${clusterTargetPort}" } # Connect to AKS cluster @@ -673,276 +180,50 @@ function connect_aks_cluster() { az aks get-credentials --resource-group ${aksClusterRGName} --name ${aksClusterName} --overwrite-existing } -# create dns alias for lb service -function create_dns_A_record() { - if [ "${enableCustomDNSAlias,,}" == "true" ]; then - ipv4Addr=$1 - label=$2 - az network dns record-set a add-record --ipv4-address ${ipv4Addr} \ - --record-set-name ${label} \ - --resource-group ${dnsRGName} \ - --zone-name ${dnsZoneName} - fi -} - -# create dns alias for app gateway -function create_dns_CNAME_record() { - if [ "${enableCustomDNSAlias,,}" == "true" ]; then - - az network dns record-set cname create \ - -g ${dnsRGName} \ - -z ${dnsZoneName} \ - -n ${dnsClusterLabel} - - az network dns record-set cname set-record \ - -g ${dnsRGName} \ - -z ${dnsZoneName} \ - --cname ${appgwAlias} \ - --record-set-name ${dnsClusterLabel} - - if [[ ${appgwForAdminServer,,} == "true" ]]; then - az network dns record-set cname create \ - -g ${dnsRGName} \ - -z ${dnsZoneName} \ - -n ${dnsAdminLabel} - - az network dns record-set cname set-record \ - -g ${dnsRGName} \ - -z ${dnsZoneName} \ - --cname ${appgwAlias} \ - --record-set-name ${dnsAdminLabel} - fi - fi -} - function create_svc_lb() { # No lb svc inputs - if [[ "${lbSvcValues}" == "[]" ]]; then - return - fi - - query_admin_target_port - query_cluster_target_port - - # Parse lb svc input values - # Generate valid json - ret=$(echo $lbSvcValues | sed "s/\:/\\\"\:\\\"/g" | - sed "s/{/{\"/g" | - sed "s/}/\"}/g" | - sed "s/,/\",\"/g" | - sed "s/}\",\"{/},{/g" | - tr -d \(\)) - - cat <${scriptDir}/lbConfiguration.json -${ret} -EOF - - array=$(jq -r '.[] | "\(.colName),\(.colTarget),\(.colPort)"' ${scriptDir}/lbConfiguration.json) - for item in $array; do - # LB config for admin-server - target=$(cut -d',' -f2 <<<$item) - if [[ "${target}" == "adminServer" ]]; then - adminServerLBSVCNamePrefix=$(cut -d',' -f1 <<<$item) - adminServerLBSVCName="${adminServerLBSVCNamePrefix}-svc-lb-admin" - adminLBPort=$(cut -d',' -f3 <<<$item) - - generate_admin_lb_definicion - - kubectl apply -f ${scriptDir}/admin-server-lb.yaml - waitfor_svc_completed ${adminServerLBSVCName} - - adminServerEndpoint=$(kubectl get svc ${adminServerLBSVCName} -n ${wlsDomainNS} -o=jsonpath='{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}') - adminConsoleEndpoint="${adminServerEndpoint}/console" - - create_dns_A_record "${adminServerEndpoint%%:*}" ${dnsAdminLabel} - - if [ "${enableCustomDNSAlias,,}" == "true" ]; then - adminConsoleEndpoint="${dnsAdminLabel}.${dnsZoneName}:${adminServerEndpoint#*:}/console" - fi - else - clusterLBSVCNamePrefix=$(cut -d',' -f1 <<<$item) - clusterLBSVCName="${clusterLBSVCNamePrefix}-svc-lb-cluster" - clusterLBPort=$(cut -d',' -f3 <<<$item) - - generate_cluster_lb_definicion - - kubectl apply -f ${scriptDir}/cluster-lb.yaml - waitfor_svc_completed ${clusterLBSVCName} - - clusterEndpoint=$(kubectl get svc ${clusterLBSVCName} -n ${wlsDomainNS} -o=jsonpath='{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}') - - create_dns_A_record "${clusterEndpoint%%:*}" ${dnsClusterLabel} - - if [ "${enableCustomDNSAlias,,}" == "true" ]; then - clusterEndpoint="${dnsClusterLabel}.${dnsZoneName}:${clusterEndpoint#*:}/" - fi - fi - done -} - -# Create network peers for aks and appgw -function network_peers_aks_appgw() { - # To successfully peer two virtual networks command 'az network vnet peering create' must be called twice with the values - # for --vnet-name and --remote-vnet reversed. - aksMCRGName=$(az aks show -n $aksClusterName -g $aksClusterRGName -o tsv --query "nodeResourceGroup") - ret=$(az group exists ${aksMCRGName}) - if [ "${ret,,}" == "false" ]; then - echo_stderr "AKS namaged resource group ${aksMCRGName} does not exist." - exit 1 + if [[ "${lbSvcValues}" != "[]" ]]; then + chmod ugo+x $scriptDir/createLbSvc.sh + bash $scriptDir/createLbSvc.sh \ + ${enableInternalLB} \ + ${enableCustomSSL} \ + ${enableCustomDNSAlias} \ + ${dnsRGName} \ + ${dnsZoneName} \ + ${dnsAdminLabel} \ + ${dnszoneAdminT3ChannelLabel} \ + ${dnsClusterLabel} \ + ${dnszoneClusterT3ChannelLabel} \ + "${lbSvcValues}" \ + ${wlsDomainUID} fi - - aksNetWorkId=$(az resource list -g ${aksMCRGName} --resource-type Microsoft.Network/virtualNetworks -o tsv --query '[*].id') - aksNetworkName=$(az resource list -g ${aksMCRGName} --resource-type Microsoft.Network/virtualNetworks -o tsv --query '[*].name') - az network vnet peering create \ - --name aks-appgw-peer \ - --remote-vnet ${aksNetWorkId} \ - --resource-group ${curRGName} \ - --vnet-name ${vnetName} \ - --allow-vnet-access - validate_status "Create network peers for $aksNetWorkId and ${vnetName}." - - appgwNetworkId=$(az resource list -g ${curRGName} --name ${vnetName} -o tsv --query '[*].id') - az network vnet peering create \ - --name aks-appgw-peer \ - --remote-vnet ${appgwNetworkId} \ - --resource-group ${aksMCRGName} \ - --vnet-name ${aksNetworkName} \ - --allow-vnet-access - - validate_status "Create network peers for $aksNetWorkId and ${vnetName}." - - # For Kbectl network plugin: https://azure.github.io/application-gateway-kubernetes-ingress/how-tos/networking/#with-kubenet - # find route table used by aks cluster - routeTableId=$(az network route-table list -g $aksMCRGName --query "[].id | [0]" -o tsv) - - # get the application gateway's subnet - appGatewaySubnetId=$(az network application-gateway show -n $appgwName -g $curRGName -o tsv --query "gatewayIpConfigurations[0].subnet.id") - - # associate the route table to Application Gateway's subnet - az network vnet subnet update \ - --ids $appGatewaySubnetId \ - --route-table $routeTableId - - validate_status "Associate the route table ${routeTableId} to Application Gateway's subnet ${appGatewaySubnetId}" } - - function create_appgw_ingress() { - if [[ "${enableAppGWIngress,,}" != "true" ]]; then - return + if [[ "${enableAppGWIngress,,}" == "true" ]]; then + chmod ugo+x $scriptDir/createAppGatewayIngress.sh + echo "$spBase64String" "$appgwFrontendSSLCertPsw" | + bash $scriptDir/createAppGatewayIngress.sh \ + ${aksClusterRGName} \ + ${aksClusterName} \ + ${wlsDomainUID} \ + ${subID} \ + ${curRGName} \ + ${appgwName} \ + ${vnetName} \ + ${appgwForAdminServer} \ + ${enableCustomDNSAlias} \ + ${dnsRGName} \ + ${dnsZoneName} \ + ${dnsAdminLabel} \ + ${dnsClusterLabel} \ + ${appgwAlias} \ + ${appgwFrontendSSLCertData} \ + ${appgwCertificateOption} \ + ${enableCustomSSL} \ + ${enableCookieBasedAffinity} \ + ${enableRemoteConsole} fi - - query_admin_target_port - query_cluster_target_port - network_peers_aks_appgw - - # create sa and bind cluster-admin role - kubectl apply -f ${scriptDir}/appgw-ingress-clusterAdmin-roleBinding.yaml - - # Keep the aad pod identity controller installation, may be used for CNI network usage - # Install aad pod identity controller - # https://github.com/Azure/aad-pod-identity - # latestAADPodIdentity=$(curl -s https://api.github.com/repos/Azure/aad-pod-identity/releases/latest \ - # | grep "browser_download_url.*deployment-rbac.yaml" \ - # | cut -d : -f 2,3 \ - # | tr -d \") - - # kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/v1.8.0/deploy/infra/deployment-rbac.yaml - - install_helm - - helm repo add application-gateway-kubernetes-ingress ${appgwIngressHelmRepo} - helm repo update - - # Keep the identity parsing, may be used for CNI network usage - # {type:UserAssigned,userAssignedIdentities:{/subscriptions/05887623-95c5-4e50-a71c-6e1c738794e2/resourceGroups/haiche-identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/wls-aks-mvp:{}}} - # identityId=${identity#*userAssignedIdentities:\{} - # identityId=${identityId%%:\{\}*} - # query identity client id - # identityClientId=$(az identity show --ids ${identityId} -o tsv --query "clientId") - - # generate Helm config - customAppgwHelmConfig=${scriptDir}/appgw-helm-config.yaml - cp ${scriptDir}/appgw-helm-config.yaml.template ${customAppgwHelmConfig} - subID=${subID#*\/subscriptions\/} - sed -i -e "s:@SUB_ID@:${subID}:g" ${customAppgwHelmConfig} - sed -i -e "s:@APPGW_RG_NAME@:${curRGName}:g" ${customAppgwHelmConfig} - sed -i -e "s:@APPGW_NAME@:${appgwName}:g" ${customAppgwHelmConfig} - sed -i -e "s:@WATCH_NAMESPACE@:${wlsDomainNS}:g" ${customAppgwHelmConfig} - # sed -i -e "s:@INDENTITY_ID@:${identityId}:g" ${customAppgwHelmConfig} - # sed -i -e "s:@IDENTITY_CLIENT_ID@:${identityClientId}:g" ${customAppgwHelmConfig} - sed -i -e "s:@SP_ENCODING_CREDENTIALS@:${spBase64String}:g" ${customAppgwHelmConfig} - - helm install ingress-azure \ - -f ${customAppgwHelmConfig} \ - application-gateway-kubernetes-ingress/ingress-azure \ - --version ${azureAppgwIngressVersion} - - validate_status "Install app gateway ingress controller." - - attempts=0 - podState="running" - while [ ! "$podState" == "completed" ] && [ $attempts -lt ${perfPodAttemps} ]; do - podState="completed" - attempts=$((attempts + 1)) - echo Waiting for Pod running...${attempts} - sleep ${perfRetryInterval} - - ret=$(kubectl get pod | grep "ingress-azure") - if [ -z "${ret}" ]; then - podState="running" - - if [ $attempts -ge ${perfPodAttemps} ]; then - echo_stderr "Failed to install app gateway ingress controller." - exit 1 - fi - fi - done - - # create tsl secret - output_create_gateway_ssl_k8s_secret - - - if [[ "${enableCustomSSL,,}" == "true" ]];then - az network application-gateway root-cert list \ - --gateway-name $appgwName \ - --resource-group $curRGName \ - | jq '.[] | .name' | grep "${appgwBackendSecretName}" - - validate_status "check if backend cert exists." - fi - - # generate ingress svc config for cluster - generate_appgw_cluster_config_file - kubectl apply -f ${clusterAppgwIngressYamlPath} - validate_status "Create appgw ingress svc." - waitfor_svc_completed ${clusterIngressName} - # expose https if e2e ssl is not set up. - if [[ "${enableCustomSSL,,}" != "true" ]];then - kubectl apply -f ${clusterAppgwIngressHttpsYamlPath} - validate_status "Create appgw ingress https svc." - waitfor_svc_completed ${clusterIngressHttpsName} - fi - - if [[ "${appgwForAdminServer,,}" == "true" ]]; then - generate_appgw_admin_config_file - kubectl apply -f ${adminAppgwIngressYamlPath} - validate_status "Create appgw ingress svc." - waitfor_svc_completed ${adminIngressName} - fi - - if [[ "${enableRemoteConsole,,}" == "true" ]]; then - export adminRemoteIngressName=${wlsDomainUID}-admin-remote-appgw-ingress-svc - export adminRemoteAppgwIngressYamlPath=${scriptDir}/appgw-admin-remote-ingress-svc.yaml - generate_appgw_admin_remote_config_file - - kubectl apply -f ${adminRemoteAppgwIngressYamlPath} - validate_status "Create appgw ingress svc." - waitfor_svc_completed ${adminRemoteIngressName} - fi - - create_dns_CNAME_record } # Main script @@ -975,29 +256,8 @@ export appgwCertificateOption=${20} export enableCustomSSL=${21} export enableCookieBasedAffinity=${22} export enableRemoteConsole=${23} - -export adminServerName="admin-server" -export adminConsoleEndpoint="null" -export appgwIngressHelmRepo="https://appgwingress.blob.core.windows.net/ingress-azure-helm-package/" -export appgwFrontCertFileName="appgw-frontend-cert.pfx" -export appgwFrontCertKeyDecrytedFileName="appgw-frontend-cert.key" -export appgwFrontCertKeyFileName="appgw-frontend-cert-decryted.key" -export appgwFrontPublicCertFileName="appgw-frontend-cert.crt" -export appgwFrontendSecretName="frontend-tls" -export appgwBackendSecretName="backend-tls" -export appgwSelfsignedCert="generateCert" -export azureAppgwIngressVersion="1.4.0" -export clusterName="cluster-1" -export clusterEndpoint="null" -export httpsListenerName="myHttpsListenerName$(date +%s)" -export httpsRuleName="myHttpsRule$(date +%s)" -export perfRetryInterval=30 # seconds -export perfPodAttemps=5 -export perfSVCAttemps=10 -export sharedPath="/shared" -export svcAdminServer="${wlsDomainUID}-${adminServerName}" -export svcCluster="${wlsDomainUID}-cluster-${clusterName}" -export wlsDomainNS="${wlsDomainUID}-ns" +export dnszoneAdminT3ChannelLabel=${24} +export dnszoneClusterT3ChannelLabel=${25} read_sensitive_parameters_from_stdin @@ -1010,5 +270,3 @@ connect_aks_cluster create_svc_lb create_appgw_ingress - -output_result diff --git a/weblogic-azure-aks/src/main/arm/scripts/setupWLSDomain.sh b/weblogic-azure-aks/src/main/arm/scripts/setupWLSDomain.sh index 58cf72e90..b95814e1f 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/setupWLSDomain.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/setupWLSDomain.sh @@ -11,7 +11,8 @@ function read_sensitive_parameters_from_stdin() { #Function to display usage message function usage() { - usage=$(cat <<-END + usage=$( + cat <<-END Usage: echo | ./setupWLSDomain.sh @@ -39,8 +40,12 @@ echo + + + + END -) + ) echo_stdout ${usage} if [ $1 -eq 1 ]; then echo_stderr ${usage} @@ -174,6 +179,35 @@ function validate_input() { echo_stderr "enablePV is required. " usage 1 fi + + if [ -z "$enableAdminT3Tunneling" ]; then + echo_stderr "enableAdminT3Tunneling is required. " + usage 1 + fi + + if [ -z "$enableClusterT3Tunneling" ]; then + echo_stderr "enableClusterT3Tunneling is required. " + usage 1 + fi + + if [ -z "$t3AdminPort" ]; then + echo_stderr "t3AdminPort is required. " + usage 1 + fi + + if [ -z "$t3ClusterPort" ]; then + echo_stderr "t3ClusterPort is required. " + usage 1 + fi + + if [ -z "$wlsJavaOption" ]; then + echo_stderr "wlsJavaOption is required. " + usage 1 + fi + + if [[ "${wlsJavaOption}" == "null" ]];then + wlsJavaOption="" + fi } # Validate teminal status with $?, exit with exception if errors happen. @@ -287,13 +321,13 @@ function install_wls_operator() { echo "install the operator" helm install ${wlsOptRelease} weblogic-operator/weblogic-operator \ - --namespace ${wlsOptNameSpace} \ - --set serviceAccount=${wlsOptSA} \ - --set "enableClusterRoleBinding=true" \ - --set "domainNamespaceSelectionStrategy=LabelSelector" \ - --set "domainNamespaceLabelSelector=weblogic-operator\=enabled" \ - --version ${wlsOptVersion} \ - --wait + --namespace ${wlsOptNameSpace} \ + --set serviceAccount=${wlsOptSA} \ + --set "enableClusterRoleBinding=true" \ + --set "domainNamespaceSelectionStrategy=LabelSelector" \ + --set "domainNamespaceLabelSelector=weblogic-operator\=enabled" \ + --version ${wlsOptVersion} \ + --wait validate_status "Installing WLS operator." @@ -322,19 +356,21 @@ function query_acr_credentials() { function build_docker_image() { echo "build a new image including the new applications" chmod ugo+x $scriptDir/createVMAndBuildImage.sh - echo $azureACRPassword $ocrSSOPSW | \ + echo $azureACRPassword $ocrSSOPSW | bash $scriptDir/createVMAndBuildImage.sh \ - $currentResourceGroup \ - $wlsImageTag \ - $azureACRServer \ - $azureACRUserName \ - $newImageTag \ - "$appPackageUrls" \ - $ocrSSOUser \ - $wlsClusterSize \ - $enableCustomSSL \ - "$scriptURL" - + $currentResourceGroup \ + $wlsImageTag \ + $azureACRServer \ + $azureACRUserName \ + $newImageTag \ + "$appPackageUrls" \ + $ocrSSOUser \ + $wlsClusterSize \ + $enableCustomSSL \ + "$scriptURL" \ + ${enableAdminT3Tunneling} \ + ${enableClusterT3Tunneling} + az acr repository show -n ${acrName} --image aks-wls-images:${newImageTag} if [ $? -ne 0 ]; then echo "Failed to create image ${azureACRServer}/aks-wls-images:${newImageTag}" @@ -342,39 +378,21 @@ function build_docker_image() { fi } -function mount_fileshare() { - fileShareName="${azFileShareName}" - - # Disable https-only - az storage account update --name ${storageAccountName} --resource-group ${storageResourceGroup} --https-only false - +function create_source_folder_for_certificates() { mntRoot="/wls" - mntPath="$mntRoot/$storageAccountName/$fileShareName" + mntPath="$mntRoot/$storageAccountName/$azFileShareName" mkdir -p $mntPath - httpEndpoint=$( - az storage account show \ - --resource-group $storageResourceGroup \ - --name $storageAccountName \ - --query "primaryEndpoints.file" | tr -d '"' - ) - smbPath=$(echo $httpEndpoint | cut -c7-$(expr length $httpEndpoint))$fileShareName - - export storageAccountKey=$(az storage account keys list \ - --resource-group $storageResourceGroup \ - --account-name $storageAccountName \ - --query "[0].value" -o tsv) - - mount -t cifs $smbPath $mntPath -o username=$storageAccountName,password=$storageAccountKey,serverino,vers=3.0,file_mode=0777,dir_mode=0777 - validate_status "Mounting path." -} - -function unmount_fileshare() { - echo "unmount fileshare." - umount ${mntPath} - # Disable https-only - az storage account update --name ${storageAccountName} --resource-group ${storageResourceGroup} --https-only true + # Create a folder for certificates + securityDir=${mntPath}/security + if [ ! -d "${securityDir}" ]; then + mkdir ${mntPath}/security + else + rm -f ${mntPath}/$wlsIdentityKeyStoreFileName + rm -f ${mntPath}/$wlsTrustKeyStoreFileName + rm -f ${mntPath}/${wlsTrustKeyStoreJKSFileName} + fi } function validate_ssl_keystores() { @@ -418,18 +436,51 @@ function validate_ssl_keystores() { echo "Validate SSL key stores successfull !!" } +function upload_certificates_to_fileshare() { + expiryData=$(($(date +%s) + ${sasTokenValidTime})) + sasTokenEnd=$(date -d@"$expiryData" -u '+%Y-%m-%dT%H:%MZ') + sasToken=$(az storage share generate-sas \ + --name ${azFileShareName} \ + --account-name ${storageAccountName} \ + --https-only \ + --permissions dlrw \ + --expiry $sasTokenEnd -o tsv) + + echo "create directory security" + fsSecurityDirName="security" + utility_create_directory_to_fileshare \ + ${fsSecurityDirName} \ + ${azFileShareName} \ + ${storageAccountName} \ + $sasToken + + echo "upload $wlsIdentityKeyStoreFileName" + utility_upload_file_to_fileshare \ + ${azFileShareName} \ + ${storageAccountName} \ + "$wlsIdentityKeyStoreFileName" \ + ${mntPath}/$wlsIdentityKeyStoreFileName \ + $sasToken + + echo "upload $wlsTrustKeyStoreFileName" + utility_upload_file_to_fileshare \ + ${azFileShareName} \ + ${storageAccountName} \ + "$wlsTrustKeyStoreFileName" \ + ${mntPath}/$wlsTrustKeyStoreFileName \ + $sasToken + + echo "upload $wlsTrustKeyStoreJKSFileName" + utility_upload_file_to_fileshare \ + ${azFileShareName} \ + ${storageAccountName} \ + "$wlsTrustKeyStoreJKSFileName" \ + ${mntPath}/${wlsTrustKeyStoreJKSFileName} \ + $sasToken +} + function output_ssl_keystore() { echo "Custom SSL is enabled. Storing CertInfo as files..." - # Create a folder for certificates - securityDir=${mntPath}/security - if [ ! -d "${securityDir}" ]; then - mkdir ${mntPath}/security - else - rm -f ${mntPath}/$wlsIdentityKeyStoreFileName - rm -f ${mntPath}/$wlsTrustKeyStoreFileName - rm -f ${mntPath}/${wlsTrustKeyStoreJKSFileName} - fi - #decode cert data once again as it would got base64 encoded echo "$wlsIdentityData" | base64 -d >${mntPath}/$wlsIdentityKeyStoreFileName echo "$wlsTrustData" | base64 -d >${mntPath}/$wlsTrustKeyStoreFileName @@ -484,8 +535,8 @@ function create_pv() { export storageAccountKey=$(az storage account keys list --resource-group $storageResourceGroup --account-name $storageAccountName --query "[0].value" -o tsv) export azureSecretName="azure-secret" kubectl -n ${wlsDomainNS} create secret generic ${azureSecretName} \ - --from-literal=azurestorageaccountname=${storageAccountName} \ - --from-literal=azurestorageaccountkey=${storageAccountKey} + --from-literal=azurestorageaccountname=${storageAccountName} \ + --from-literal=azurestorageaccountkey=${storageAccountKey} # generate pv configurations customPVYaml=${scriptDir}/pv.yaml @@ -515,7 +566,7 @@ function create_pv() { } function wait_for_pod_completed() { - echo "Waiting for $((appReplicas+1)) pods are running." + echo "Waiting for $((appReplicas + 1)) pods are running." utility_wait_for_pod_completed \ ${appReplicas} \ @@ -528,8 +579,8 @@ function wait_for_image_update_completed() { # Make sure all of the pods are updated with new image. # Assumption: we have only one cluster currently. acrImagePath=${azureACRServer}/aks-wls-images:${newImageTag} - echo "Waiting for $((appReplicas+1)) new pods created with image ${acrImagePath}" - + echo "Waiting for $((appReplicas + 1)) new pods created with image ${acrImagePath}" + utility_wait_for_image_update_completed \ "${acrImagePath}" \ ${appReplicas} \ @@ -556,40 +607,39 @@ function create_domain_namespace() { fi kubectl -n ${wlsDomainNS} create secret generic \ - ${kubectlWLSCredentialName} \ - --from-literal=username=${wlsUserName} \ - --from-literal=password=${wlsPassword} + ${kubectlWLSCredentialName} \ + --from-literal=username=${wlsUserName} \ + --from-literal=password=${wlsPassword} kubectl -n ${wlsDomainNS} label secret ${kubectlWLSCredentialName} weblogic.domainUID=${wlsDomainUID} kubectl -n ${wlsDomainNS} create secret generic ${kubectlWDTEncryptionSecret} \ - --from-literal=password=${wdtRuntimePassword} + --from-literal=password=${wdtRuntimePassword} kubectl -n ${wlsDomainNS} label secret ${kubectlWDTEncryptionSecret} weblogic.domainUID=${wlsDomainUID} kubectl create secret docker-registry ${kubectlSecretForACR} \ - --docker-server=${azureACRServer} \ - --docker-username=${azureACRUserName} \ - --docker-password=${azureACRPassword} \ - -n ${wlsDomainNS} + --docker-server=${azureACRServer} \ + --docker-username=${azureACRUserName} \ + --docker-password=${azureACRPassword} \ + -n ${wlsDomainNS} kubectl -n ${wlsDomainNS} label secret ${kubectlSecretForACR} weblogic.domainUID=${wlsDomainUID} } function parsing_ssl_certs_and_create_ssl_secret() { - export javaOptions="" if [[ "${enableCustomSSL,,}" == "${constTrue}" ]]; then # use default Java, if no, install open jdk 11. - # why not Microsoft open jdk? No apk installation package! + # why not use Microsoft open jdk? No apk installation package! export JAVA_HOME=/usr/lib/jvm/default-jvm/ if [ ! -d "${JAVA_HOME}" ]; then install_jdk JAVA_HOME=/usr/lib/jvm/java-11-openjdk fi - mount_fileshare + create_source_folder_for_certificates output_ssl_keystore validate_ssl_keystores - unmount_fileshare + upload_certificates_to_fileshare echo "check if ${kubectlWLSSSLCredentialsName} exists." ret=$(kubectl get secret -n ${wlsDomainNS} | grep "${kubectlWLSSSLCredentialsName}") @@ -609,7 +659,7 @@ function parsing_ssl_certs_and_create_ssl_secret() { --from-literal=ssltruststorepassword=${wlsTrustPsw} kubectl -n ${wlsDomainNS} label secret ${kubectlWLSSSLCredentialsName} weblogic.domainUID=${wlsDomainUID} - javaOptions="-Dweblogic.security.SSL.ignoreHostnameVerification=true -Dweblogic.security.SSL.trustedCAKeyStore=${sharedPath}/${wlsTrustKeyStoreJKSFileName}" + javaOptions=" -Dweblogic.security.SSL.ignoreHostnameVerification=true -Dweblogic.security.SSL.trustedCAKeyStore=${sharedPath}/${wlsTrustKeyStoreJKSFileName} ${javaOptions}" fi } @@ -621,6 +671,13 @@ function parsing_ssl_certs_and_create_ssl_secret() { # * Deploy WebLogic domain using image in ACR # * Wait for the domain completed function setup_wls_domain() { + export javaOptions=${wlsJavaOption} + if [[ "${enableClusterT3Channel,,}" == "true" ]] || [[ "${enableAdminT3Channel,,}" == "true" ]]; then + # for remote t3/t3s access. + # refer to https://oracle.github.io/weblogic-kubernetes-operator/faq/external-clients/#enabling-unknown-host-access + javaOptions="-Dweblogic.rjvm.allowUnknownHost=true ${javaOptions}" + fi + # create namespace create_domain_namespace @@ -647,33 +704,43 @@ function setup_wls_domain() { echo "start to update domain ${wlsDomainUID}" chmod ugo+x $scriptDir/updateDomainConfig.sh bash $scriptDir/updateDomainConfig.sh \ - ${customDomainYaml} \ - ${appReplicas} \ - ${wlsCPU} \ - ${wlsDomainUID} \ - ${wlsDomainName} \ - "${azureACRServer}/aks-wls-images:${newImageTag}" \ - ${wlsMemory} \ - ${managedServerPrefix} \ - ${enableCustomSSL} \ - ${enablePV} \ - "${javaOptions}" + ${customDomainYaml} \ + ${appReplicas} \ + ${wlsCPU} \ + ${wlsDomainUID} \ + ${wlsDomainName} \ + "${azureACRServer}/aks-wls-images:${newImageTag}" \ + ${wlsMemory} \ + ${managedServerPrefix} \ + ${enableCustomSSL} \ + ${enablePV} \ + ${enableAdminT3Tunneling} \ + ${enableClusterT3Tunneling} \ + ${t3AdminPort} \ + ${t3ClusterPort} \ + ${constClusterName} \ + "${javaOptions}" else echo "start to create domain ${wlsDomainUID}" # generate domain yaml chmod ugo+x $scriptDir/genDomainConfig.sh bash $scriptDir/genDomainConfig.sh \ - ${customDomainYaml} \ - ${appReplicas} \ - ${wlsCPU} \ - ${wlsDomainUID} \ - ${wlsDomainName} \ - "${azureACRServer}/aks-wls-images:${newImageTag}" \ - ${wlsMemory} \ - ${managedServerPrefix} \ - ${enableCustomSSL} \ - ${enablePV} \ - "${javaOptions}" + ${customDomainYaml} \ + ${appReplicas} \ + ${wlsCPU} \ + ${wlsDomainUID} \ + ${wlsDomainName} \ + "${azureACRServer}/aks-wls-images:${newImageTag}" \ + ${wlsMemory} \ + ${managedServerPrefix} \ + ${enableCustomSSL} \ + ${enablePV} \ + ${enableAdminT3Tunneling} \ + ${enableClusterT3Tunneling} \ + ${t3AdminPort} \ + ${t3ClusterPort} \ + ${constClusterName} \ + "${javaOptions}" fi kubectl apply -f ${customDomainYaml} @@ -714,6 +781,11 @@ export wlsIdentityAlias=${21} export wlsTrustData=${22} export wlsTrustType=${23} export enablePV=${24} +export enableAdminT3Tunneling=${25} +export enableClusterT3Tunneling=${26} +export t3AdminPort=${27} +export t3ClusterPort=${28} +export wlsJavaOption=${29} export adminServerName="admin-server" export azFileShareName="weblogic" @@ -724,6 +796,8 @@ export kubectlWLSCredentialName="${wlsDomainUID}-weblogic-credentials" export kubectlWLSSSLCredentialsName="${wlsDomainUID}-weblogic-ssl-credentials" export newImageTag=$(date +%s) export operatorName="weblogic-operator" +# seconds +export sasTokenValidTime=3600 export storageFileShareName="weblogic" export storageResourceGroup=${currentResourceGroup} export sharedPath="/shared" diff --git a/weblogic-azure-aks/src/main/arm/scripts/updateDomainConfig.sh b/weblogic-azure-aks/src/main/arm/scripts/updateDomainConfig.sh index 17e3ebca7..86db0c86c 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/updateDomainConfig.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/updateDomainConfig.sh @@ -14,8 +14,15 @@ export wlsMemory=$7 export wlsManagedPrefix=$8 export enableSSL=${9} export enablePV=${10} -export javaOptions=${11} +export enableAdminT3Tunneling=${11} +export enableClusterT3Tunneling=${12} +export t3AdminPort=${13} +export t3ClusterPort=${14} +export clusterName=${15} +export javaOptions=${16} +export adminServiceUrl="${wlsDomainUID}-admin-server.${wlsDomainUID}-ns.svc.cluster.local" +export clusterServiceUrl="${wlsDomainUID}-cluster-${clusterName}.${wlsDomainUID}-ns.svc.cluster.local" export wlsDomainNS="${wlsDomainUID}-ns" # output the existing domain configuration @@ -150,6 +157,24 @@ if [[ "${enableSSL,,}" == "true" ]]; then EOF fi +if [[ "${enableAdminT3Tunneling,,}" == "true" ]]; then + cat <>$filePath + - name: T3_TUNNELING_ADMIN_PORT + value: "${t3AdminPort}" + - name: T3_TUNNELING_ADMIN_ADDRESS + value: "${adminServiceUrl}" +EOF +fi + +if [[ "${enableClusterT3Tunneling,,}" == "true" ]]; then + cat <>$filePath + - name: T3_TUNNELING_CLUSTER_PORT + value: "${t3ClusterPort}" + - name: T3_TUNNELING_CLUSTER_ADDRESS + value: "${clusterServiceUrl}" +EOF +fi + index=0 while [ $index -lt ${envLength} ]; do envItemName=$(cat ${previousConfig} | jq ". | .spec.serverPod.env[$index] | .name" | tr -d "\"") @@ -168,7 +193,11 @@ while [ $index -lt ${envLength} ]; do || [[ "${envItemName}" == "SSL_IDENTITY_PRIVATE_KEYSTORE_PSW" ]] \ || [[ "${envItemName}" == "SSL_TRUST_KEYSTORE_PATH" ]] \ || [[ "${envItemName}" == "SSL_TRUST_KEYSTORE_TYPE" ]] \ - || [[ "${envItemName}" == "SSL_TRUST_KEYSTORE_PSW" ]];then + || [[ "${envItemName}" == "SSL_TRUST_KEYSTORE_PSW" ]] \ + || [[ "${envItemName}" == "T3_TUNNELING_ADMIN_PORT" ]] \ + || [[ "${envItemName}" == "T3_TUNNELING_ADMIN_ADDRESS" ]] \ + || [[ "${envItemName}" == "T3_TUNNELING_CLUSTER_PORT" ]] \ + || [[ "${envItemName}" == "T3_TUNNELING_CLUSTER_ADDRESS" ]];then continue fi diff --git a/weblogic-azure-aks/src/main/arm/scripts/utility.sh b/weblogic-azure-aks/src/main/arm/scripts/utility.sh index b23d2006d..f2eb83bef 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/utility.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/utility.sh @@ -2,6 +2,31 @@ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. # This script runs on Azure Container Instance with Alpine Linux that Azure Deployment script creates. +function echo_stderr() { + echo >&2 "$@" + # The function is used for scripts running within Azure Deployment Script + # The value of AZ_SCRIPTS_OUTPUT_PATH is /mnt/azscripts/azscriptoutput + echo -e "$@" >>${AZ_SCRIPTS_PATH_OUTPUT_DIRECTORY}/errors.log +} + +function echo_stdout() { + echo "$@" + # The function is used for scripts running within Azure Deployment Script + # The value of AZ_SCRIPTS_OUTPUT_PATH is /mnt/azscripts/azscriptoutput + echo -e "$@" >>${AZ_SCRIPTS_PATH_OUTPUT_DIRECTORY}/debug.log +} + +#Validate teminal status with $?, exit with exception if errors happen. +function utility_validate_status() { + if [ $? == 1 ]; then + echo_stderr "$@" + echo_stderr "Errors happen, exit 1." + exit 1 + else + echo_stdout "$@" + fi +} + function install_jdk() { # Install Microsoft OpenJDK apk --no-cache add openjdk11 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community @@ -9,6 +34,7 @@ function install_jdk() { echo "java version" java -version if [ $? -eq 1 ]; then + echo_stderr "Failed to install open jdk 11." exit 1 fi # JAVA_HOME=/usr/lib/jvm/java-11-openjdk @@ -20,49 +46,102 @@ function install_kubectl() { echo "validate kubectl" kubectl --help if [ $? -eq 1 ]; then - echo "Failed to install kubectl." + echo_stderr "Failed to install kubectl." exit 1 fi } -function echo_stderr() { - >&2 echo "$@" - # The function is used for scripts running within Azure Deployment Script - # The value of AZ_SCRIPTS_OUTPUT_PATH is /mnt/azscripts/azscriptoutput - echo -e "$@" >>${AZ_SCRIPTS_PATH_OUTPUT_DIRECTORY}/errors.log +function install_helm() { + # Install Helm + browserURL=$(curl -m ${curlMaxTime} -s https://api.github.com/repos/helm/helm/releases/latest | + grep "browser_download_url.*linux-amd64.tar.gz.asc" | + cut -d : -f 2,3 | + tr -d \") + helmLatestVersion=${browserURL#*download\/} + helmLatestVersion=${helmLatestVersion%%\/helm*} + helmPackageName=helm-${helmLatestVersion}-linux-amd64.tar.gz + curl -m ${curlMaxTime} -fL https://get.helm.sh/${helmPackageName} -o /tmp/${helmPackageName} + tar -zxvf /tmp/${helmPackageName} -C /tmp + mv /tmp/linux-amd64/helm /usr/local/bin/helm + echo "Helm version" + helm version + utility_validate_status "Finished installing Helm." } -function echo_stdout() { - echo "$@" - # The function is used for scripts running within Azure Deployment Script - # The value of AZ_SCRIPTS_OUTPUT_PATH is /mnt/azscripts/azscriptoutput - echo -e "$@" >>${AZ_SCRIPTS_PATH_OUTPUT_DIRECTORY}/debug.log +# Query service port +# $1: service name +# $2: namespace +# $3: channel name +# return: port +# Notes: channel name will be different if istio is enabled. +function utility_query_service_port() { + local port=$(kubectl get service ${1} -n ${2} -o json | + jq ".spec.ports[] | select(.name==\"${3}\") | .port") + if [ $? != 0 ] || [[ "$port" == "null" ]]; then + echo_stderr "Failed to query port of ${1}/${3} in namespace ${2}" + exit 1 + fi + + echo $port } # # Check the state of a persistent volume. -# Leverage source code from function "checkPvState" in weblogic-operator, kubernetes\samples\scripts\common\utility.sh +# Leverage source code from function "checkPvState" in weblogic-operator, kubernetes\samples\scripts\common\utility.sh # $1 - name of volume # $2 - expected state of volume # $3 - max attempt # $4 - interval function utility_check_pv_state { - echo_stdout "Checking if the persistent volume ${1:?} is ${2:?}" - local pv_state=`kubectl get pv $1 -o jsonpath='{.status.phase}'` - attempts=0 - while [ ! "$pv_state" = "$2" ] && [ ! $attempts -eq $3 ]; do - attempts=$((attempts + 1)) - sleep $4 - pv_state=`kubectl get pv $1 -o jsonpath='{.status.phase}'` - done - if [ "$pv_state" != "$2" ]; then - echo_stderr "The persistent volume state should be $2 but is $pv_state" - exit 1 - fi + echo_stdout "Checking if the persistent volume ${1:?} is ${2:?}" + local pv_state=$(kubectl get pv $1 -o jsonpath='{.status.phase}') + attempts=0 + while [ ! "$pv_state" = "$2" ] && [ ! $attempts -eq $3 ]; do + attempts=$((attempts + 1)) + sleep $4 + pv_state=$(kubectl get pv $1 -o jsonpath='{.status.phase}') + done + if [ "$pv_state" != "$2" ]; then + echo_stderr "The persistent volume state should be $2 but is $pv_state" + exit 1 + fi } -# Call this function to make sure pods of a domain are running. +# +# Create directory in specified file share +# $1 - name of directory +# $2 - name of file share +# $3 - name of storage account +# $4 - sas token +function utility_create_directory_to_fileshare() { + ret=$(az storage directory exists --name $1 --share-name $2 --account-name $3 --sas-token ${4} | jq '.exists') + if [[ "${ret,,}" == "false" ]]; then + az storage directory create --name $1 --share-name $2 --account-name $3 --sas-token ${4} --timeout 30 + fi + + if [ $? != 0 ]; then + echo_stderr "Failed to create directory ${1} in file share ${3}/${2}" + exit 1 + fi +} + +# +# Upload file to file share +# $1 - name of file share +# $2 - name of storage account +# $3 - path of file +# $4 - source path of file +# $5 - sas token +function utility_upload_file_to_fileshare() { + az storage file upload --share-name ${1} --account-name ${2} --path ${3} --source ${4} --sas-token ${5} --timeout 60 + if [ $? != 0 ]; then + echo_stderr "Failed to upload ${3} to file share ${2}/${1}" + exit 1 + fi +} + +# Call this function to make sure pods of a domain are running. # * Make sure the admin server pod is running # * Make sure all the managed server pods are running # Assuming there is only one cluster in the domain @@ -77,34 +156,33 @@ function utility_wait_for_pod_completed() { checkPodStatusMaxAttemps=$3 checkPodStatusInterval=$4 - echo "Waiting for $((appReplicas+1)) pods are running." + echo "Waiting for $((appReplicas + 1)) pods are running." readyPodNum=0 attempt=0 - while [[ ${readyPodNum} -le ${appReplicas} && $attempt -le ${checkPodStatusMaxAttemps} ]];do - ret=$(kubectl get pods -n ${wlsDomainNS} -o json \ - | jq '.items[] | .status.phase' \ - | grep "Running") - if [ -z "${ret}" ];then + while [[ ${readyPodNum} -le ${appReplicas} && $attempt -le ${checkPodStatusMaxAttemps} ]]; do + ret=$(kubectl get pods -n ${wlsDomainNS} -o json | + jq '.items[] | .status.phase' | + grep "Running") + if [ -z "${ret}" ]; then readyPodNum=0 else - readyPodNum=$(kubectl get pods -n ${wlsDomainNS} -o json \ - | jq '.items[] | .status.phase' \ - | grep -c "Running") + readyPodNum=$(kubectl get pods -n ${wlsDomainNS} -o json | + jq '.items[] | .status.phase' | + grep -c "Running") fi echo "Number of new running pod: ${readyPodNum}" - attempt=$((attempt+1)) + attempt=$((attempt + 1)) sleep ${checkPodStatusInterval} done - if [ ${attempt} -gt ${checkPodStatusMaxAttemps} ];then - echo "It takes too long to wait for all the pods are running, please refer to http://oracle.github.io/weblogic-kubernetes-operator/samples/simple/azure-kubernetes-service/#troubleshooting" + if [ ${attempt} -gt ${checkPodStatusMaxAttemps} ]; then + echo_stderr "It takes too long to wait for all the pods are running, please refer to http://oracle.github.io/weblogic-kubernetes-operator/samples/simple/azure-kubernetes-service/#troubleshooting" exit 1 fi } - -# Call this function to make sure pods of a domain are updated with expected image. +# Call this function to make sure pods of a domain are updated with expected image. # * Make sure the admin server pod is updated with expected image # * Make sure all the managed server pods are updated with expected image # Assuming there is only one cluster in the domain @@ -123,31 +201,31 @@ function utility_wait_for_image_update_completed() { checkPodStatusMaxAttemps=$4 checkPodStatusInterval=$5 - echo "Waiting for $((appReplicas+1)) new pods created with image ${acrImagePath}" - + echo "Waiting for $((appReplicas + 1)) new pods created with image ${acrImagePath}" + updatedPodNum=0 attempt=0 - while [ ${updatedPodNum} -le ${appReplicas} ] && [ $attempt -le ${checkPodStatusMaxAttemps} ];do + while [ ${updatedPodNum} -le ${appReplicas} ] && [ $attempt -le ${checkPodStatusMaxAttemps} ]; do echo "attempts ${attempt}" - ret=$(kubectl get pods -n ${wlsDomainNS} -o json \ - | jq '.items[] | .spec | .containers[] | select(.name == "weblogic-server") | .image' \ - | grep "${acrImagePath}") - - if [ -z "${ret}" ];then + ret=$(kubectl get pods -n ${wlsDomainNS} -o json | + jq '.items[] | .spec | .containers[] | select(.name == "weblogic-server") | .image' | + grep "${acrImagePath}") + + if [ -z "${ret}" ]; then updatedPodNum=0 else - updatedPodNum=$(kubectl get pods -n ${wlsDomainNS} -o json \ - | jq '.items[] | .spec | .containers[] | select(.name == "weblogic-server") | .image' \ - | grep -c "${acrImagePath}") + updatedPodNum=$(kubectl get pods -n ${wlsDomainNS} -o json | + jq '.items[] | .spec | .containers[] | select(.name == "weblogic-server") | .image' | + grep -c "${acrImagePath}") fi echo "Number of new pod: ${updatedPodNum}" - attempt=$((attempt+1)) + attempt=$((attempt + 1)) sleep ${checkPodStatusInterval} done - if [ ${attempt} -gt ${checkPodStatusMaxAttemps} ];then - echo "Failed to update image ${acrImagePath} to all weblogic server pods. " + if [ ${attempt} -gt ${checkPodStatusMaxAttemps} ]; then + echo_stderr "Failed to update image ${acrImagePath} to all weblogic server pods. " exit 1 fi } @@ -171,11 +249,11 @@ function utility_wait_for_pod_restarted() { updatedPodNum=0 attempt=0 - while [ ${updatedPodNum} -le ${appReplicas} ] && [ $attempt -le ${checkPodStatusMaxAttemps} ];do + while [ ${updatedPodNum} -le ${appReplicas} ] && [ $attempt -le ${checkPodStatusMaxAttemps} ]; do echo "attempts ${attempt}" - ret=$(kubectl get pods -n ${wlsDomainNS} -l weblogic.domainUID=${wlsDomainUID} -o json \ - | jq '.items[] | .metadata.creationTimestamp' | tr -d "\"") - + ret=$(kubectl get pods -n ${wlsDomainNS} -l weblogic.domainUID=${wlsDomainUID} -o json | + jq '.items[] | .metadata.creationTimestamp' | tr -d "\"") + counter=0 for item in $ret; do # conver the time format from YYYY-MM-DDThh:mm:ssZ to YYYY.MM.DD-hh:mm:ss @@ -183,19 +261,48 @@ function utility_wait_for_pod_restarted() { podCreateTimeStamp=$(date -u -d "${alpineItem}" +"%s") echo "pod create time: $podCreateTimeStamp, base time: ${baseTime}" if [ ${podCreateTimeStamp} -gt ${baseTime} ]; then - counter=$((counter+1)) + counter=$((counter + 1)) fi done updatedPodNum=$counter echo "Number of new pod: ${updatedPodNum}" - attempt=$((attempt+1)) + attempt=$((attempt + 1)) sleep ${checkPodStatusInterval} done - if [ ${attempt} -gt ${checkPodStatusMaxAttemps} ];then - echo "Failed to restart all weblogic server pods. " + if [ ${attempt} -gt ${checkPodStatusMaxAttemps} ]; then + echo_stderr "Failed to restart all weblogic server pods. " + exit 1 + fi +} + +# Call this function to make sure the lb service is avaliable. +function utility_waitfor_lb_svc_completed() { + svcName=$1 + wlsDomainNS=$2 + perfSVCAttemps=$3 + perfRetryInterval=$4 + + attempts=0 + svcState="running" + while [ "$svcState" == "running" ] && [ $attempts -lt ${perfSVCAttemps} ]; do + svcState="completed" + attempts=$((attempts + 1)) + echo Waiting for job completed...${attempts} + sleep ${perfRetryInterval} + + ip=$(kubectl get svc ${svcName} -n ${wlsDomainNS} -o json | + jq '.status.loadBalancer.ingress[0].ip') + echo "ip: ${ip}" + if [[ "${ip}" == "null" ]]; then + svcState="running" + fi + done + + if [ "$svcState" == "running" ] && [ $attempts -ge ${perfSVCAttemps} ]; then + echo_stderr "Failed to create service: ${svcName}" exit 1 fi -} \ No newline at end of file +} diff --git a/weblogic-azure-aks/src/main/bicep/mainTemplate.bicep b/weblogic-azure-aks/src/main/bicep/mainTemplate.bicep index bc4b8196e..497302265 100644 --- a/weblogic-azure-aks/src/main/bicep/mainTemplate.bicep +++ b/weblogic-azure-aks/src/main/bicep/mainTemplate.bicep @@ -93,10 +93,14 @@ param dbPassword string = newGuid() param dbUser string = 'contosoDbUser' @description('DNS prefix for ApplicationGateway') param dnsNameforApplicationGateway string = 'wlsgw' -@description('Azure DNS Zone name.') +@description('Specify a label used to generate subdomain of Admin server. The final subdomain name will be label.dnszoneName, e.g. admin.contoso.xyz') param dnszoneAdminConsoleLabel string = 'admin' -@description('Specify a label used to generate subdomain of Application Gateway. The final subdomain name will be label.dnszoneName, e.g. applications.contoso.xyz') -param dnszoneAppGatewayLabel string = 'www' +@description('Specify a label used to generate subdomain of Admin server T3 channel. The final subdomain name will be label.dnszoneName, e.g. admin-t3.contoso.xyz') +param dnszoneAdminT3ChannelLabel string = 'admin-t3' +@description('Specify a label used to generate subdomain of WebLogic cluster. The final subdomain name will be label.dnszoneName, e.g. applications.contoso.xyz') +param dnszoneClusterLabel string = 'www' +param dnszoneClusterT3ChannelLabel string = 'cluster-t3' +@description('Azure DNS Zone name.') param dnszoneName string = 'contoso.xyz' param dnszoneRGName string = 'dns-contoso-rg' @description('JDBC Connection String') @@ -112,6 +116,10 @@ param enableCookieBasedAffinity bool = false param enableCustomSSL bool = false param enableDB bool = false param enableDNSConfiguration bool = false +@description('Configure a custom channel in Admin Server for the T3 protocol that enables HTTP tunneling') +param enableAdminT3Tunneling bool = false +@description('Configure a custom channel in WebLogic cluster for the T3 protocol that enables HTTP tunneling') +param enableClusterT3Tunneling bool = false @description('An user assigned managed identity. Make sure the identity has permission to create/update/delete/list Azure resources.') param identity object @description('JNDI Name for JDBC Datasource') @@ -202,6 +210,10 @@ param sslUploadedPrivateKeyAlias string = 'contoso' @secure() @description('Password of the private key') param sslUploadedPrivateKeyPassPhrase string = newGuid() +@description('Public port of the custom T3 channel in admin server') +param t3ChannelAdminPort int = 7005 +@description('Public port of the custom T3 channel in WebLoigc cluster') +param t3ChannelClusterPort int = 8011 @description('True to set up internal load balancer service.') param useInternalLB bool = false @description('ture to upload Java EE applications and deploy the applications to WebLogic domain.') @@ -219,6 +231,7 @@ param wlsDomainName string = 'domain1' param wlsDomainUID string = 'sample-domain1' @description('Docker tag that comes after "container-registry.oracle.com/middleware/weblogic:"') param wlsImageTag string = '12.2.1.4' +param wlsJavaOption string = 'null' @description('Memory requests for admin server and managed server.') param wlsMemory string = '1.5Gi' @secure() @@ -243,6 +256,7 @@ var const_hasStorageAccount = !createAKSCluster && reference('query-existing-sto var const_identityKeyStoreType = (sslConfigurationAccessOption == const_wlsSSLCertOptionKeyVault) ? sslKeyVaultCustomIdentityKeyStoreType : sslUploadedCustomIdentityKeyStoreType var const_keyvaultNameFromTag = const_hasTags && contains(resourceGroup().tags, name_tagNameForKeyVault) ? resourceGroup().tags.wlsKeyVault : '' var const_trustKeyStoreType = (sslConfigurationAccessOption == const_wlsSSLCertOptionKeyVault) ? sslKeyVaultCustomTrustKeyStoreType : sslUploadedCustomTrustKeyStoreType +var const_wlsJavaOptions = wlsJavaOption == '' ? 'null' : wlsJavaOption var const_wlsSSLCertOptionKeyVault = 'keyVaultStoredConfig' var name_defaultPidDeployment = 'pid' var name_dnsNameforApplicationGateway = '${concat(dnsNameforApplicationGateway, take(utcValue, 6))}' @@ -338,6 +352,8 @@ module wlsDomainDeployment 'modules/setupWebLogicCluster.bicep' = if (!enableCus createStorageAccount: const_bCreateStorageAccount enableAzureMonitoring: enableAzureMonitoring enableCustomSSL: enableCustomSSL + enableAdminT3Tunneling: enableAdminT3Tunneling + enableClusterT3Tunneling: enableClusterT3Tunneling enablePV: const_enablePV identity: identity location: location @@ -345,6 +361,8 @@ module wlsDomainDeployment 'modules/setupWebLogicCluster.bicep' = if (!enableCus ocrSSOPSW: ocrSSOPSW ocrSSOUser: ocrSSOUser storageAccountName: name_storageAccountName + t3ChannelAdminPort: t3ChannelAdminPort + t3ChannelClusterPort: t3ChannelClusterPort wdtRuntimePassword: wdtRuntimePassword wlsClusterSize: wlsClusterSize wlsCPU: wlsCPU @@ -354,6 +372,7 @@ module wlsDomainDeployment 'modules/setupWebLogicCluster.bicep' = if (!enableCus wlsIdentityKeyStorePassphrase: sslUploadedCustomIdentityKeyStorePassphrase wlsIdentityKeyStoreType: const_defaultKeystoreType wlsImageTag: wlsImageTag + wlsJavaOption: const_wlsJavaOptions wlsMemory: wlsMemory wlsPassword: wlsPassword wlsPrivateKeyAlias: sslUploadedPrivateKeyAlias @@ -394,6 +413,8 @@ module wlsDomainWithCustomSSLDeployment 'modules/setupWebLogicCluster.bicep' = i createStorageAccount: const_bCreateStorageAccount enableAzureMonitoring: enableAzureMonitoring enableCustomSSL: enableCustomSSL + enableAdminT3Tunneling: enableAdminT3Tunneling + enableClusterT3Tunneling: enableClusterT3Tunneling enablePV: const_enablePV identity: identity location: location @@ -401,6 +422,8 @@ module wlsDomainWithCustomSSLDeployment 'modules/setupWebLogicCluster.bicep' = i ocrSSOPSW: ocrSSOPSW ocrSSOUser: ocrSSOUser storageAccountName: name_storageAccountName + t3ChannelAdminPort: t3ChannelAdminPort + t3ChannelClusterPort: t3ChannelClusterPort wdtRuntimePassword: wdtRuntimePassword wlsClusterSize: wlsClusterSize wlsCPU: wlsCPU @@ -410,6 +433,7 @@ module wlsDomainWithCustomSSLDeployment 'modules/setupWebLogicCluster.bicep' = i wlsIdentityKeyStorePassphrase: sslKeyvault.getSecret(name_identityKeyStorePswSecret) wlsIdentityKeyStoreType: const_identityKeyStoreType wlsImageTag: wlsImageTag + wlsJavaOption: const_wlsJavaOptions wlsMemory: wlsMemory wlsPassword: wlsPassword wlsPrivateKeyAlias: sslKeyvault.getSecret(name_privateKeyAliasSecret) @@ -478,7 +502,9 @@ module networkingDeployment 'modules/networking.bicep' = if (const_enableNetwork createDNSZone: createDNSZone dnsNameforApplicationGateway: name_domainLabelforApplicationGateway dnszoneAdminConsoleLabel: dnszoneAdminConsoleLabel - dnszoneAppGatewayLabel: dnszoneAppGatewayLabel + dnszoneAdminT3ChannelLabel: dnszoneAdminT3ChannelLabel + dnszoneClusterLabel: dnszoneClusterLabel + dnszoneClusterT3ChannelLabel: dnszoneClusterT3ChannelLabel dnszoneName: dnszoneName dnszoneRGName: dnszoneRGName enableAppGWIngress: enableAppGWIngress @@ -533,8 +559,13 @@ output adminConsoleInternalUrl string = ref_wlsDomainDeployment.outputs.adminSer output adminConsoleExternalUrl string = const_enableNetworking ? networkingDeployment.outputs.adminConsoleExternalUrl : '' output adminConsoleExternalSecuredUrl string = const_enableNetworking ? networkingDeployment.outputs.adminConsoleExternalSecuredUrl : '' // If TLS/SSL enabled, only secured url is working, will not output HTTP url. -output adminRemoteConsoleUrl string = const_enableNetworking && !enableCustomSSL ? networkingDeployment.outputs.adminRemoteConsoleUrl: '' -output adminRemoteConsoleSecuredUrl string = const_enableNetworking ? networkingDeployment.outputs.adminRemoteConsoleSecuredUrl: '' +output adminRemoteConsoleUrl string = const_enableNetworking && !enableCustomSSL ? networkingDeployment.outputs.adminRemoteConsoleUrl : '' +output adminRemoteConsoleSecuredUrl string = const_enableNetworking ? networkingDeployment.outputs.adminRemoteConsoleSecuredUrl : '' +output adminServerT3InternalUrl string = ref_wlsDomainDeployment.outputs.adminServerT3InternalUrl.value +output adminServerT3ExternalUrl string = enableAdminT3Tunneling && const_enableNetworking ? format('{0}://{1}', enableCustomSSL ? 't3s' : 't3', networkingDeployment.outputs.adminServerT3ChannelUrl) : '' output clusterInternalUrl string = ref_wlsDomainDeployment.outputs.clusterSVCUrl.value output clusterExternalUrl string = const_enableNetworking ? networkingDeployment.outputs.clusterExternalUrl : '' output clusterExternalSecuredUrl string = const_enableNetworking ? networkingDeployment.outputs.clusterExternalSecuredUrl : '' +output clusterT3InternalUrl string = ref_wlsDomainDeployment.outputs.clusterT3InternalUrl.value +output clusterT3ExternalUrl string = enableAdminT3Tunneling && const_enableNetworking ? format('{0}://{1}', enableCustomSSL ? 't3s' : 't3', networkingDeployment.outputs.clusterT3ChannelUrl) : '' + diff --git a/weblogic-azure-aks/src/main/bicep/modules/_azure-resoruces/_dnsZones.bicep b/weblogic-azure-aks/src/main/bicep/modules/_azure-resoruces/_dnsZones.bicep index ae220178f..c5dba80b3 100644 --- a/weblogic-azure-aks/src/main/bicep/modules/_azure-resoruces/_dnsZones.bicep +++ b/weblogic-azure-aks/src/main/bicep/modules/_azure-resoruces/_dnsZones.bicep @@ -1,12 +1,9 @@ @description('Azure DNS Zone name.') param dnszoneName string -@description('Location for all resources.') -param location string - resource dnszoneName_resource 'Microsoft.Network/dnszones@2018-05-01' = { name: dnszoneName - location: location + location: 'global' properties: { zoneType: 'Public' } diff --git a/weblogic-azure-aks/src/main/bicep/modules/_azure-resoruces/_keyvaultForGateway.bicep b/weblogic-azure-aks/src/main/bicep/modules/_azure-resoruces/_keyvaultForGateway.bicep index 70fd23fb7..5e682f89a 100644 --- a/weblogic-azure-aks/src/main/bicep/modules/_azure-resoruces/_keyvaultForGateway.bicep +++ b/weblogic-azure-aks/src/main/bicep/modules/_azure-resoruces/_keyvaultForGateway.bicep @@ -76,6 +76,10 @@ module keyvaultBackendRootCert '_keyvault/_keyvaultForGatewayBackendCert.bicep' keyVaultName: keyVaultName sku: sku } + dependsOn:[ + keyVaultwithSelfSignedAppGatewaySSLCert + keyVaultwithExistingAppGatewaySSLCert + ] } output keyVaultName string = (useExistingAppGatewaySSLCertificate ? keyVaultwithExistingAppGatewaySSLCert.outputs.keyVaultName : keyVaultwithSelfSignedAppGatewaySSLCert.outputs.keyVaultName) diff --git a/weblogic-azure-aks/src/main/bicep/modules/_deployment-scripts/_ds-create-networking.bicep b/weblogic-azure-aks/src/main/bicep/modules/_deployment-scripts/_ds-create-networking.bicep index d4a08390a..ffed6373a 100644 --- a/weblogic-azure-aks/src/main/bicep/modules/_deployment-scripts/_ds-create-networking.bicep +++ b/weblogic-azure-aks/src/main/bicep/modules/_deployment-scripts/_ds-create-networking.bicep @@ -23,7 +23,9 @@ param appgwFrontendSSLCertPsw string = newGuid() param aksClusterRGName string = 'aks-contoso-rg' param aksClusterName string = 'aks-contoso' param dnszoneAdminConsoleLabel string = 'admin' -param dnszoneAppGatewayLabel string = 'www' +param dnszoneAdminT3ChannelLabel string ='admin-t3' +param dnszoneClusterLabel string = 'www' +param dnszoneClusterT3ChannelLabel string = 'cluster-t3' param dnszoneName string = 'contoso.xyz' param dnszoneRGName string = 'dns-contoso-rg' param enableAppGWIngress bool = false @@ -43,11 +45,15 @@ param wlsDomainUID string = 'sample-domain1' var const_appgwHelmConfigTemplate='appgw-helm-config.yaml.template' var const_appgwSARoleBindingFile='appgw-ingress-clusterAdmin-roleBinding.yaml' -var const_arguments = '${aksClusterRGName} ${aksClusterName} ${wlsDomainName} ${wlsDomainUID} "${string(lbSvcValues)}" ${enableAppGWIngress} ${subscription().id} ${resourceGroup().name} ${appgwName} ${vnetName} ${string(servicePrincipal)} ${appgwForAdminServer} ${enableDNSConfiguration} ${dnszoneRGName} ${dnszoneName} ${dnszoneAdminConsoleLabel} ${dnszoneAppGatewayLabel} ${appgwAlias} ${useInternalLB} ${appgwFrontendSSLCertData} ${appgwFrontendSSLCertPsw} ${appgwCertificateOption} ${enableCustomSSL} ${enableCookieBasedAffinity} ${appgwForRemoteConsole}' +var const_arguments = '${aksClusterRGName} ${aksClusterName} ${wlsDomainName} ${wlsDomainUID} "${string(lbSvcValues)}" ${enableAppGWIngress} ${subscription().id} ${resourceGroup().name} ${appgwName} ${vnetName} ${string(servicePrincipal)} ${appgwForAdminServer} ${enableDNSConfiguration} ${dnszoneRGName} ${dnszoneName} ${dnszoneAdminConsoleLabel} ${dnszoneClusterLabel} ${appgwAlias} ${useInternalLB} ${appgwFrontendSSLCertData} ${appgwFrontendSSLCertPsw} ${appgwCertificateOption} ${enableCustomSSL} ${enableCookieBasedAffinity} ${appgwForRemoteConsole} ${dnszoneAdminT3ChannelLabel} ${dnszoneClusterT3ChannelLabel}' var const_commonScript = 'common.sh' +var const_createDnsRecordScript = 'createDnsRecord.sh' +var const_createLbSvcScript = 'createLbSvc.sh' +var const_createGatewayIngressSvcScript = 'createAppGatewayIngress.sh' var const_scriptLocation = uri(_artifactsLocation, 'scripts/') var const_setupNetworkingScript= 'setupNetworking.sh' var const_primaryScript = 'invokeSetupNetworking.sh' +var const_utilityScript= 'utility.sh' resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { name: 'ds-networking-deployment' @@ -63,6 +69,10 @@ resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { uri(const_scriptLocation, '${const_appgwHelmConfigTemplate}${_artifactsLocationSasToken}') uri(const_scriptLocation, '${const_appgwSARoleBindingFile}${_artifactsLocationSasToken}') uri(const_scriptLocation, '${const_commonScript}${_artifactsLocationSasToken}') + uri(const_scriptLocation, '${const_utilityScript}${_artifactsLocationSasToken}') + uri(const_scriptLocation, '${const_createDnsRecordScript}${_artifactsLocationSasToken}') + uri(const_scriptLocation, '${const_createLbSvcScript}${_artifactsLocationSasToken}') + uri(const_scriptLocation, '${const_createGatewayIngressSvcScript}${_artifactsLocationSasToken}') ] cleanupPreference: 'OnSuccess' retentionInterval: 'P1D' @@ -71,5 +81,7 @@ resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { } output adminConsoleLBUrl string = length(lbSvcValues) > 0 && (reference('ds-networking-deployment').outputs.adminConsoleEndpoint != 'null') ? format('http://{0}/',reference('ds-networking-deployment').outputs.adminConsoleEndpoint): '' +output adminServerT3LBUrl string = length(lbSvcValues) > 0 && (reference('ds-networking-deployment').outputs.adminServerT3Endpoint != 'null') ? reference('ds-networking-deployment').outputs.adminServerT3Endpoint: '' output clusterLBUrl string = length(lbSvcValues) > 0 && (reference('ds-networking-deployment').outputs.clusterEndpoint != 'null') ? format('http://{0}/',reference('ds-networking-deployment').outputs.clusterEndpoint): '' +output clusterT3LBUrl string = length(lbSvcValues) > 0 && (reference('ds-networking-deployment').outputs.clusterT3Endpoint != 'null') ? reference('ds-networking-deployment').outputs.clusterT3Endpoint: '' diff --git a/weblogic-azure-aks/src/main/bicep/modules/_deployment-scripts/_ds-create-wls-cluster.bicep b/weblogic-azure-aks/src/main/bicep/modules/_deployment-scripts/_ds-create-wls-cluster.bicep index a2616977c..6ae022f00 100644 --- a/weblogic-azure-aks/src/main/bicep/modules/_deployment-scripts/_ds-create-wls-cluster.bicep +++ b/weblogic-azure-aks/src/main/bicep/modules/_deployment-scripts/_ds-create-wls-cluster.bicep @@ -11,6 +11,8 @@ param acrName string = '' param appPackageUrls array = [] param appReplicas int = 2 param enableCustomSSL bool = false +param enableAdminT3Tunneling bool = false +param enableClusterT3Tunneling bool = false param enablePV bool = false param identity object param location string = 'eastus' @@ -19,6 +21,8 @@ param managedServerPrefix string = 'managed-server' param ocrSSOPSW string param ocrSSOUser string param storageAccountName string = 'null' +param t3ChannelAdminPort int = 7005 +param t3ChannelClusterPort int = 8011 param utcValue string = utcNow() @secure() param wdtRuntimePassword string @@ -35,6 +39,7 @@ param wlsIdentityKeyStorePassphrase string = newGuid() ]) param wlsIdentityKeyStoreType string = 'PKCS12' param wlsImageTag string = '12.2.1.4' +param wlsJavaOption string = 'null' param wlsMemory string = '1.5Gi' @secure() param wlsPassword string @@ -51,7 +56,7 @@ param wlsTrustKeyStorePassPhrase string = newGuid() param wlsTrustKeyStoreType string = 'PKCS12' param wlsUserName string = 'weblogic' -var const_arguments = '${ocrSSOUser} ${ocrSSOPSW} ${aksClusterRGName} ${aksClusterName} ${wlsImageTag} ${acrName} ${wlsDomainName} ${wlsDomainUID} ${wlsUserName} ${wlsPassword} ${wdtRuntimePassword} ${wlsCPU} ${wlsMemory} ${managedServerPrefix} ${appReplicas} ${string(appPackageUrls)} ${resourceGroup().name} ${const_scriptLocation} ${storageAccountName} ${wlsClusterSize} ${enableCustomSSL} ${wlsIdentityKeyStoreData} ${wlsIdentityKeyStorePassphrase} ${wlsIdentityKeyStoreType} ${wlsPrivateKeyAlias} ${wlsPrivateKeyPassPhrase} ${wlsTrustKeyStoreData} ${wlsTrustKeyStorePassPhrase} ${wlsTrustKeyStoreType} ${enablePV} ' +var const_arguments = '${ocrSSOUser} ${ocrSSOPSW} ${aksClusterRGName} ${aksClusterName} ${wlsImageTag} ${acrName} ${wlsDomainName} ${wlsDomainUID} ${wlsUserName} ${wlsPassword} ${wdtRuntimePassword} ${wlsCPU} ${wlsMemory} ${managedServerPrefix} ${appReplicas} ${string(appPackageUrls)} ${resourceGroup().name} ${const_scriptLocation} ${storageAccountName} ${wlsClusterSize} ${enableCustomSSL} ${wlsIdentityKeyStoreData} ${wlsIdentityKeyStorePassphrase} ${wlsIdentityKeyStoreType} ${wlsPrivateKeyAlias} ${wlsPrivateKeyPassPhrase} ${wlsTrustKeyStoreData} ${wlsTrustKeyStorePassPhrase} ${wlsTrustKeyStoreType} ${enablePV} ${enableAdminT3Tunneling} ${enableClusterT3Tunneling} ${t3ChannelAdminPort} ${t3ChannelClusterPort} "${wlsJavaOption}"' var const_buildDockerImageScript='createVMAndBuildImage.sh' var const_commonScript = 'common.sh' var const_invokeSetUpDomainScript = 'invokeSetupWLSDomain.sh' diff --git a/weblogic-azure-aks/src/main/bicep/modules/networking.bicep b/weblogic-azure-aks/src/main/bicep/modules/networking.bicep index 72447b7ea..a0d7438b4 100644 --- a/weblogic-azure-aks/src/main/bicep/modules/networking.bicep +++ b/weblogic-azure-aks/src/main/bicep/modules/networking.bicep @@ -32,8 +32,10 @@ param dnsNameforApplicationGateway string = 'wlsgw' @description('Azure DNS Zone name.') param dnszoneName string = 'contoso.xyz' param dnszoneAdminConsoleLabel string = 'admin' -@description('Specify a label used to generate subdomain of Application Gateway. The final subdomain name will be label.dnszoneName, e.g. applications.contoso.xyz') -param dnszoneAppGatewayLabel string = 'www' +param dnszoneAdminT3ChannelLabel string ='admin-t3' +@description('Specify a label used to generate subdomain of WebLogic cluster. The final subdomain name will be label.dnszoneName, e.g. applications.contoso.xyz') +param dnszoneClusterLabel string = 'www' +param dnszoneClusterT3ChannelLabel string = 'cluster-t3' param dnszoneRGName string = 'dns-contoso-rg' @description('true to set up Application Gateway ingress.') param enableAppGWIngress bool = false @@ -62,9 +64,11 @@ param wlsDomainName string = 'domain1' @description('UID of WebLogic domain, used in WebLogic Operator.') param wlsDomainUID string = 'sample-domain1' -var const_appgwCustomDNSAlias = format('{0}.{1}/', dnszoneAppGatewayLabel, dnszoneName) +var const_appgwCustomDNSAlias = format('{0}.{1}/', dnszoneClusterLabel, dnszoneName) var const_appgwAdminCustomDNSAlias = format('{0}.{1}/', dnszoneAdminConsoleLabel, dnszoneName) var const_appgwSSLCertOptionGenerateCert = 'generateCert' +var name_networkDeployment = enableAppGWIngress ? (appGatewayCertificateOption == const_appgwSSLCertOptionGenerateCert ? 'ds-networking-deployment-1': 'ds-networking-deployment') : 'ds-networking-deployment-2' +var ref_networkDeployment = reference(name_networkDeployment) module pidNetworkingStart './_pids/_pid.bicep' = { name: 'pid-networking-start-deployment' @@ -105,7 +109,7 @@ module appgwDeployment '_azure-resoruces/_appgateway.bicep' = if (enableAppGWIng module appgwBackendCertDeployment '_deployment-scripts/_ds-appgw-upload-trusted-root-certificate.bicep' = if (enableAppGWIngress && enableCustomSSL) { name: 'app-gateway-backend-cert-deployment' params: { - appgwName: appgwDeployment.outputs.appGatewayName + appgwName: enableAppGWIngress ? appgwDeployment.outputs.appGatewayName : 'null' sslBackendRootCertData: existingKeyvault.getSecret(keyvaultBackendCertDataSecretName) identity: identity } @@ -120,7 +124,6 @@ module dnsZoneDeployment '_azure-resoruces/_dnsZones.bicep' = if (enableDNSConfi name: 'dnszone-deployment' params: { dnszoneName: dnszoneName - location: location } dependsOn: [ pidNetworkingStart @@ -142,7 +145,9 @@ module networkingDeployment '_deployment-scripts/_ds-create-networking.bicep' = aksClusterRGName: aksClusterRGName aksClusterName: aksClusterName dnszoneAdminConsoleLabel: dnszoneAdminConsoleLabel - dnszoneAppGatewayLabel: dnszoneAppGatewayLabel + dnszoneAdminT3ChannelLabel: dnszoneAdminT3ChannelLabel + dnszoneClusterLabel: dnszoneClusterLabel + dnszoneClusterT3ChannelLabel: dnszoneClusterT3ChannelLabel dnszoneName: dnszoneName dnszoneRGName: createDNSZone ? resourceGroup().name : dnszoneRGName enableAppGWIngress: enableAppGWIngress @@ -180,7 +185,9 @@ module networkingDeployment2 '_deployment-scripts/_ds-create-networking.bicep' = aksClusterRGName: aksClusterRGName aksClusterName: aksClusterName dnszoneAdminConsoleLabel: dnszoneAdminConsoleLabel - dnszoneAppGatewayLabel: dnszoneAppGatewayLabel + dnszoneAdminT3ChannelLabel: dnszoneAdminT3ChannelLabel + dnszoneClusterLabel: dnszoneClusterLabel + dnszoneClusterT3ChannelLabel: dnszoneClusterT3ChannelLabel dnszoneName: dnszoneName dnszoneRGName: createDNSZone ? resourceGroup().name : dnszoneRGName enableAppGWIngress: enableAppGWIngress @@ -207,8 +214,8 @@ module networkingDeployment3 '_deployment-scripts/_ds-create-networking.bicep' = params: { _artifactsLocation: _artifactsLocation _artifactsLocationSasToken: _artifactsLocationSasToken - appgwName: enableAppGWIngress ? appgwDeployment.outputs.appGatewayName : 'null' - appgwAlias: enableAppGWIngress ? appgwDeployment.outputs.appGatewayAlias : 'null' + appgwName: 'null' + appgwAlias: 'null' appgwCertificateOption: appGatewayCertificateOption appgwForAdminServer: appgwForAdminServer appgwForRemoteConsole: appgwForRemoteConsole @@ -217,7 +224,9 @@ module networkingDeployment3 '_deployment-scripts/_ds-create-networking.bicep' = aksClusterRGName: aksClusterRGName aksClusterName: aksClusterName dnszoneAdminConsoleLabel: dnszoneAdminConsoleLabel - dnszoneAppGatewayLabel: dnszoneAppGatewayLabel + dnszoneAdminT3ChannelLabel: dnszoneAdminT3ChannelLabel + dnszoneClusterLabel: dnszoneClusterLabel + dnszoneClusterT3ChannelLabel: dnszoneClusterT3ChannelLabel dnszoneName: dnszoneName dnszoneRGName: createDNSZone ? resourceGroup().name : dnszoneRGName enableAppGWIngress: enableAppGWIngress @@ -229,12 +238,11 @@ module networkingDeployment3 '_deployment-scripts/_ds-create-networking.bicep' = location: location servicePrincipal: servicePrincipal useInternalLB: useInternalLB - vnetName: enableAppGWIngress ? appgwDeployment.outputs.vnetName : 'null' + vnetName: 'null' wlsDomainName: wlsDomainName wlsDomainUID: wlsDomainUID } dependsOn: [ - appgwBackendCertDeployment dnsZoneDeployment ] } @@ -245,7 +253,7 @@ module pidAppgwEnd './_pids/_pid.bicep' = if (enableAppGWIngress) { name: _pidAppgwEnd } dependsOn: [ - networkingDeployment + appgwDeployment ] } @@ -255,7 +263,9 @@ module pidNetworkingEnd './_pids/_pid.bicep' = { name: _pidNetworkingEnd } dependsOn: [ - pidAppgwEnd + networkingDeployment + networkingDeployment2 + networkingDeployment3 ] } @@ -263,5 +273,7 @@ output adminConsoleExternalUrl string = enableAppGWIngress ? (enableDNSConfigura output adminConsoleExternalSecuredUrl string = enableAppGWIngress && enableCustomSSL && enableDNSConfiguration ? format('https://{0}console', const_appgwAdminCustomDNSAlias) : '' output adminRemoteConsoleUrl string = enableAppGWIngress ? (enableDNSConfiguration ? format('http://{0}remoteconsole', const_appgwAdminCustomDNSAlias) : format('http://{0}/remoteconsole', appgwDeployment.outputs.appGatewayAlias)) : networkingDeployment3.outputs.adminConsoleLBUrl output adminRemoteConsoleSecuredUrl string = enableAppGWIngress && enableCustomSSL && enableDNSConfiguration ? format('https://{0}remoteconsole', const_appgwAdminCustomDNSAlias) : '' +output adminServerT3ChannelUrl string = ref_networkDeployment.outputs.adminServerT3LBUrl.value output clusterExternalUrl string = enableAppGWIngress ? (enableDNSConfiguration ? format('http://{0}', const_appgwCustomDNSAlias) : appgwDeployment.outputs.appGatewayURL) : networkingDeployment3.outputs.clusterLBUrl output clusterExternalSecuredUrl string = enableAppGWIngress ? (enableDNSConfiguration ? format('https://{0}', const_appgwCustomDNSAlias) : appgwDeployment.outputs.appGatewaySecuredURL) : '' +output clusterT3ChannelUrl string = ref_networkDeployment.outputs.clusterT3LBUrl.value diff --git a/weblogic-azure-aks/src/main/bicep/modules/setupWebLogicCluster.bicep b/weblogic-azure-aks/src/main/bicep/modules/setupWebLogicCluster.bicep index b081b3f46..8281508fc 100644 --- a/weblogic-azure-aks/src/main/bicep/modules/setupWebLogicCluster.bicep +++ b/weblogic-azure-aks/src/main/bicep/modules/setupWebLogicCluster.bicep @@ -57,6 +57,8 @@ param createStorageAccount bool = false param enableAzureMonitoring bool = false @description('true to create persistent volume using file share.') param enableCustomSSL bool = false +param enableAdminT3Tunneling bool = false +param enableClusterT3Tunneling bool = false param enablePV bool = false @description('An user assigned managed identity. Make sure the identity has permission to create/update/delete/list Azure resources.') param identity object @@ -69,6 +71,8 @@ param ocrSSOPSW string @description('User name of Oracle SSO account.') param ocrSSOUser string param storageAccountName string +param t3ChannelAdminPort int = 7005 +param t3ChannelClusterPort int = 8011 @secure() @description('Password for model WebLogic Deploy Tooling runtime encrytion.') param wdtRuntimePassword string @@ -91,6 +95,7 @@ param wlsIdentityKeyStorePassphrase string = newGuid() param wlsIdentityKeyStoreType string = 'PKCS12' @description('Docker tag that comes after "container-registry.oracle.com/middleware/weblogic:"') param wlsImageTag string = '12.2.1.4' +param wlsJavaOption string = 'null' @description('Memory requests for admin server and managed server.') param wlsMemory string = '1.5Gi' @secure() @@ -181,13 +186,17 @@ module wlsDomainDeployment './_deployment-scripts/_ds-create-wls-cluster.bicep' appPackageUrls: appPackageUrls appReplicas: appReplicas enableCustomSSL: enableCustomSSL + enableAdminT3Tunneling: enableAdminT3Tunneling + enableClusterT3Tunneling: enableClusterT3Tunneling enablePV: enablePV identity: identity location: location managedServerPrefix: managedServerPrefix - storageAccountName: storageAccountName ocrSSOUser: ocrSSOUser ocrSSOPSW: ocrSSOPSW + storageAccountName: storageAccountName + t3ChannelAdminPort: t3ChannelAdminPort + t3ChannelClusterPort: t3ChannelClusterPort wdtRuntimePassword: wdtRuntimePassword wlsClusterSize: wlsClusterSize wlsCPU: wlsCPU @@ -197,6 +206,7 @@ module wlsDomainDeployment './_deployment-scripts/_ds-create-wls-cluster.bicep' wlsIdentityKeyStorePassphrase: wlsIdentityKeyStorePassphrase wlsIdentityKeyStoreType: wlsIdentityKeyStoreType wlsImageTag: wlsImageTag + wlsJavaOption: wlsJavaOption wlsMemory: wlsMemory wlsPassword: wlsPassword wlsPrivateKeyAlias: wlsPrivateKeyAlias @@ -230,4 +240,6 @@ module pidEnd './_pids/_pid.bicep' = { output aksClusterName string = createAKSCluster ? aksClusterDeployment.outputs.aksClusterName : aksClusterName output aksClusterRGName string = createAKSCluster ? resourceGroup().name : aksClusterRGName output adminServerUrl string = format('http://{0}-admin-server.{0}-ns.svc.cluster.local:7001/console', wlsDomainUID) +output adminServerT3InternalUrl string = enableAdminT3Tunneling ? format('{0}://{1}-admin-server.{1}-ns.svc.cluster.local:{2}', enableCustomSSL ? 't3s' : 't3', wlsDomainUID, t3ChannelAdminPort): '' output clusterSVCUrl string = format('http://{0}-cluster-cluster-1.{0}-ns.svc.cluster.local:8001/', wlsDomainUID) +output clusterT3InternalUrl string = enableClusterT3Tunneling ? format('{0}://{1}-cluster-cluster-1.{1}-ns.svc.cluster.local:{2}', enableCustomSSL ? 't3s' : 't3', wlsDomainUID, t3ChannelClusterPort): '' diff --git a/weblogic-azure-aks/src/resources/ejb-client-stateless-1.0.0.war b/weblogic-azure-aks/src/resources/ejb-client-stateless-1.0.0.war new file mode 100644 index 000000000..2028d66b4 Binary files /dev/null and b/weblogic-azure-aks/src/resources/ejb-client-stateless-1.0.0.war differ diff --git a/weblogic-azure-aks/src/resources/ejb-server-stateless-1.0.0.jar b/weblogic-azure-aks/src/resources/ejb-server-stateless-1.0.0.jar new file mode 100644 index 000000000..1c2d04522 Binary files /dev/null and b/weblogic-azure-aks/src/resources/ejb-server-stateless-1.0.0.jar differ