From a2fd0732baf59fb748bcdfa7b1b939deb2ed5f82 Mon Sep 17 00:00:00 2001 From: Anand Sirasagi Date: Wed, 19 May 2021 15:12:56 +0530 Subject: [PATCH 1/8] Oracle WebCenter Portal 12.2.1.4.0 on Kubernetes Signed-off-by: Anand Sirasagi --- CODEOWNERS | 1 + OracleWebCenterPortal/kubernetes/README.md | 15 + .../kubernetes/charts/traefik/values.yaml | 34 + .../common/create-domain-job.sh | 30 + .../common/createWebCenterPortalDomain.py | 411 ++ .../domain-home-on-pv/common/utility.sh | 55 + .../create-domain-inputs.yaml | 197 + .../create-domain-job-template.yaml | 98 + .../domain-home-on-pv/create-domain.sh | 292 ++ .../delete-domain-job-template.yaml | 62 + .../wlst/create-domain-script.sh | 35 + .../WebLogicLoggingExporter.yaml | 9 + .../config/config_as.yml | 63 + .../config/config_ms.yml | 63 + .../config/weblogic.xml | 18 + .../weblogic-monitoring-exporter/get1.1.0.sh | 38 + .../wls-exporter.yaml | 42 + .../es-loadbalancer.yaml | 15 + .../create-wcp-es-cluster/es-pvpvc.yaml | 29 + .../create-wcp-es-cluster/es-secret.yaml | 13 + .../create-wcp-es-cluster/es-service.yaml | 19 + .../create-wcp-es-cluster/es-statefulset.yaml | 114 + .../imagetool-scripts/additionalBuildCmds.txt | 30 + .../kubernetes/imagetool-scripts/buildArgs | 10 + .../kubernetes/ingress-per-domain/Chart.yaml | 8 + .../kubernetes/ingress-per-domain/README.md | 100 + .../templates/nginx-ingress.yaml | 63 + .../templates/traefik-ingress.yaml | 54 + .../templates/voyager-ingress.yaml | 79 + .../ingress-per-domain/tls/nginx-tls.yaml | 25 + .../ingress-per-domain/tls/traefik-tls.yaml | 20 + .../ingress-per-domain/tls/voyager-tls.yaml | 27 + .../kubernetes/ingress-per-domain/values.yaml | 41 + README.md | 1 + .../content/wcportal-domains/_index.md | 45 + .../wcportal-domains/appendix/_index.md | 9 + .../appendix/docker-k8s-hardening.md | 26 + .../appendix/quickstart-deployment-on-prem.md | 750 ++++ .../appendix/wcp-cluster-sizing-info.md | 18 + .../wcportal-domains/cleanup-domain-setup.md | 38 + .../create-or-update-image/_index.md | 1173 ++++++ .../wcportal-domains/installguide/_index.md | 11 + .../configure-wcp-search/_index.md | 266 ++ .../installguide/create-wcp-domain/_index.md | 392 ++ .../prepare-your-environment/_index.md | 355 ++ .../installguide/prerequisites/_index.md | 50 + .../manage-wcportal-domains/_index.md | 13 + .../configure-load-balancer/_index.md | 13 + .../configure-load-balancer/apachewebtier.md | 195 + .../configure-load-balancer/nginx.md | 403 ++ .../configure-load-balancer/traefik.md | 496 +++ .../configure-load-balancer/voyager.md | 526 +++ .../monitoring-and-publishing-logs/_index.md | 12 + .../monitoring-domain/_index.md | 286 ++ .../images/wcp-graphana-dashboard.png | Bin 0 -> 216980 bytes .../images/wme-deploy-contextroot.png | Bin 0 -> 83596 bytes .../images/wme-deploy-target-server.png | Bin 0 -> 169397 bytes .../monitoring-domain/images/wme-deploy.png | Bin 0 -> 65335 bytes .../images/wme-gp-add-datasource.png | Bin 0 -> 120555 bytes .../images/wme-gp-import-json.png | Bin 0 -> 34638 bytes .../images/wme-service-discovery.png | Bin 0 -> 127015 bytes .../monitoring-domain/images/wme-test-url.png | Bin 0 -> 64502 bytes .../monitoring-domain/weblogic_dashboard.json | 3312 +++++++++++++++++ .../publishing-logs/_index.md | 11 + .../publishing-logs/fluentd/_index.md | 382 ++ .../fluentd/wcp-kibana-dashboard.png | Bin 0 -> 159602 bytes ...-Logging-Exporter_target-startup-class.png | Bin 0 -> 111603 bytes .../publishing-logs/weblogiclogging/_index.md | 142 + .../weblogiclogging/wcp-kibana-dashboard.png | Bin 0 -> 133313 bytes .../wle-startup-shutdown-class.png | Bin 0 -> 74657 bytes .../content/wcportal-domains/release-notes.md | 12 + 71 files changed, 11047 insertions(+) create mode 100644 OracleWebCenterPortal/kubernetes/README.md create mode 100755 OracleWebCenterPortal/kubernetes/charts/traefik/values.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/create-domain-job.sh create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/utility.sh create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-job-template.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain.sh create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/delete-domain-job-template.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/wlst/create-domain-script.sh create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_as.yml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_ms.yml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/weblogic.xml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/get1.1.0.sh create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-loadbalancer.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-pvpvc.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-secret.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-service.yaml create mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-statefulset.yaml create mode 100755 OracleWebCenterPortal/kubernetes/imagetool-scripts/additionalBuildCmds.txt create mode 100755 OracleWebCenterPortal/kubernetes/imagetool-scripts/buildArgs create mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/Chart.yaml create mode 100644 OracleWebCenterPortal/kubernetes/ingress-per-domain/README.md create mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/nginx-ingress.yaml create mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/traefik-ingress.yaml create mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/voyager-ingress.yaml create mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/nginx-tls.yaml create mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/traefik-tls.yaml create mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/voyager-tls.yaml create mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/values.yaml create mode 100644 docs-source/content/wcportal-domains/_index.md create mode 100644 docs-source/content/wcportal-domains/appendix/_index.md create mode 100644 docs-source/content/wcportal-domains/appendix/docker-k8s-hardening.md create mode 100644 docs-source/content/wcportal-domains/appendix/quickstart-deployment-on-prem.md create mode 100644 docs-source/content/wcportal-domains/appendix/wcp-cluster-sizing-info.md create mode 100644 docs-source/content/wcportal-domains/cleanup-domain-setup.md create mode 100644 docs-source/content/wcportal-domains/create-or-update-image/_index.md create mode 100644 docs-source/content/wcportal-domains/installguide/_index.md create mode 100644 docs-source/content/wcportal-domains/installguide/configure-wcp-search/_index.md create mode 100644 docs-source/content/wcportal-domains/installguide/create-wcp-domain/_index.md create mode 100644 docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md create mode 100644 docs-source/content/wcportal-domains/installguide/prerequisites/_index.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/_index.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/_index.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/apachewebtier.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/voyager.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/_index.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/_index.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wcp-graphana-dashboard.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-deploy-contextroot.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-deploy-target-server.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-deploy.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-gp-add-datasource.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-gp-import-json.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-service-discovery.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-test-url.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/weblogic_dashboard.json create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/_index.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/_index.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/wcp-kibana-dashboard.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/WebLogic-Logging-Exporter_target-startup-class.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/_index.md create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/wcp-kibana-dashboard.png create mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/wle-startup-shutdown-class.png create mode 100644 docs-source/content/wcportal-domains/release-notes.md diff --git a/CODEOWNERS b/CODEOWNERS index 42cc85c45..f143e37a2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -8,4 +8,5 @@ /OracleUnifiedDirectory/ @kuldeepbshah @surya902 @pratdash-orcl /OracleUnifiedDirectorySM/ @kuldeepbshah @surya902 @pratdash-orcl /OracleWebCenterContent/ @deboghos @pjadam +/OracleWebCenterPortal/ @anandsirasagi /OracleWebCenterSites/ @prshshuk diff --git a/OracleWebCenterPortal/kubernetes/README.md b/OracleWebCenterPortal/kubernetes/README.md new file mode 100644 index 000000000..80153b2a0 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/README.md @@ -0,0 +1,15 @@ +# Oracle WebCenter Portal on Kubernetes + +This directory provides the open source samples which have several key features to assist you with deploying and managing WebCenter Portal in a Kubernetes environment. You can do the following: + +* Create WebCenter Portal instances in a Kubernetes persistent volume. This persistent volume can reside in an NFS file system or other Kubernetes volume types. +* Start servers based on declarative startup parameters and desired states. +* Expose the WebCenter Portal Services for external access. +* Configure WebCenter Portal for Search. +* Publish WebLogic Kubernetes Operator and WebLogic Server logs into Elasticsearch and interact with them in Kibana. +* Monitor the instance using Prometheus and Grafana + +#### Getting started + +Refer the following documentation link for detailed information about deploying Oracle WebCenter Portal domain on Kubernetes. +[Documentation](https://oracle.github.io/fmw-kubernetes/wcportal-domains/) diff --git a/OracleWebCenterPortal/kubernetes/charts/traefik/values.yaml b/OracleWebCenterPortal/kubernetes/charts/traefik/values.yaml new file mode 100755 index 000000000..3acc04e5a --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/traefik/values.yaml @@ -0,0 +1,34 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +image: + name: traefik + tag: 2.2.8 + pullPolicy: IfNotPresent +ingressRoute: + dashboard: + enabled: true + annotations: {} + labels: {} +providers: + kubernetesCRD: + enabled: true + kubernetesIngress: + enabled: true +ports: + traefik: + port: 9000 + expose: true + exposedPort: 9000 + protocol: TCP + web: + port: 8000 + expose: true + exposedPort: 30305 + nodePort: 30305 + protocol: TCP + websecure: + port: 8443 + expose: true + exposedPort: 30443 + protocol: TCP + nodePort: 30443 \ No newline at end of file diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/create-domain-job.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/create-domain-job.sh new file mode 100755 index 000000000..4894581cf --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/create-domain-job.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +function exitIfError { + if [ "$1" != "0" ]; then + echo "$2" + exit $1 + fi +} + +# Include common utility functions +source ${CREATE_DOMAIN_SCRIPT_DIR}/utility.sh + +# Verify the script to create the domain exists +script=${CREATE_DOMAIN_SCRIPT_DIR}/create-domain-script.sh + +checkCreateDomainScript $script +checkDomainSecret +prepareDomainHomeDir + +# Execute the script to create the domain +source $script +exitIfError $? "ERROR: $script failed." + +# DON'T REMOVE THIS +# This script has to contain this log message. +# It is used to determine if the job is really completed. +echo "Successfully Completed" diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py new file mode 100755 index 000000000..d34fb8ea5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py @@ -0,0 +1,411 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +import os +import sys + +import com.oracle.cie.domain.script.jython.WLSTException as WLSTException + +class WCPortal12214Provisioner: + + MACHINES = { + 'machine1' : { + 'NMType': 'SSL', + 'ListenAddress': 'localhost', + 'ListenPort': 5658 + } + } + + MANAGED_SERVERS = [] + + JRF_12214_TEMPLATES = { + 'baseTemplate' : '@@ORACLE_HOME@@/wlserver/common/templates/wls/wls.jar', + 'extensionTemplates' : [ + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.jrf_template.jar', + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.jrf.ws.async_template.jar', + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.wsmpm_template.jar', + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.ums_template.jar', + '@@ORACLE_HOME@@/em/common/templates/wls/oracle.em_wls_template.jar' + ], + 'serverGroupsToTarget' : [ 'JRF-MAN-SVR', 'WSMPM-MAN-SVR' ] + } + + WCPortal_12214_TEMPLATES = { + 'extensionTemplates' : [ + '@@ORACLE_HOME@@/wcportal/common/templates/wls/oracle.wc_spaces_template.jar', + '@@ORACLE_HOME@@/wcportal/common/templates/wls/oracle.analyticscollector_template.jar' + ], + 'serverGroupsToTarget' : [ 'SPACES-MGD-SVRS' ] + } + + def __init__(self, oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName): + self.oracleHome = self.validateDirectory(oracleHome) + self.javaHome = self.validateDirectory(javaHome) + self.domainParentDir = self.validateDirectory(domainParentDir, create=True) + return + + def createWCPortalDomain(self, domainName, user, password, db, dbPrefix, dbPassword, adminListenPort, adminName, + managedNameBase, managedServerPort, prodMode, managedCount, clusterName, sslEnabled, adminServerSSLPort, managedServerSSLPort, + exposeAdminT3Channel=None, t3ChannelPublicAddress=None, t3ChannelPort=None): + + print '=================================================================' + print ' WebCenter Portal Weblogic Operator Domain Creation Script ' + print ' 12.2.1.4 ' + print '=================================================================' + + print 'Creating Base Domain...' + domainHome = self.createBaseDomain(domainName, user, password, adminListenPort, adminServerSSLPort, adminName, managedNameBase, + managedServerPort, managedServerSSLPort, prodMode, managedCount, clusterName, sslEnabled) + + print 'Extending Domain...' + self.extendDomain(domainHome, db, dbPrefix, dbPassword, exposeAdminT3Channel, t3ChannelPublicAddress, + t3ChannelPort) + print 'Domain Creation is done...' + + + def createBaseDomain(self, domainName, user, password, adminListenPort, adminServerSSLPort, adminName, + managedNameBase, managedServerPort, managedServerSSLPort, prodMode, managedCount, clusterName ,sslEnabled): + baseTemplate = self.replaceTokens(self.JRF_12214_TEMPLATES['baseTemplate']) + + readTemplate(baseTemplate) + setOption('DomainName', domainName) + setOption('JavaHome', self.javaHome) + if (prodMode == 'true'): + setOption('ServerStartMode', 'prod') + else: + setOption('ServerStartMode', 'dev') + set('Name', domainName) + + admin_port = int(adminListenPort) + ms_port = int(managedServerPort) + ms_count = int(managedCount) + ms_sslport = int(managedServerSSLPort) + admin_sslport = int(adminServerSSLPort) + # Create Admin Server + # ======================= + print 'Creating Admin Server...' + cd('/Servers/AdminServer') + #set('ListenAddress', '%s-%s' % (domain_uid, admin_server_name_svc)) + set('ListenPort', admin_port) + set('Name', adminName) + cmo.setWeblogicPluginEnabled(true) + #Enabling SSL For AdminServer + #============================= + if (sslEnabled == 'true'): + print('Enabling SSL for Admin server...') + cd('/Servers/' + adminName) + create(adminName, 'SSL') + cd('/Servers/' + adminName + '/SSL/' + adminName) + set('ListenPort', admin_sslport) + set('Enabled', 'True') + + + # Define the user password for weblogic + # ===================================== + cd('/Security/' + domainName + '/User/weblogic') + set('Name', user) + set('Password', password) + + # Create a cluster + # ====================== + print 'Creating cluster...' + cd('/') + cl=create(clusterName, 'Cluster') + + # Create managed serversi + self.MANAGED_SERVERS = self.createManagedServers(ms_count, managedNameBase, ms_port, ms_sslport, clusterName, self.MANAGED_SERVERS, sslEnabled) + print 'Managed servers created...' + + # Create Node Manager + # ======================= + print 'Creating Node Manager...' + for machine in self.MACHINES: + cd('/') + create(machine, 'Machine') + cd('Machine/' + machine) + create(machine, 'NodeManager') + cd('NodeManager/' + machine) + for param in self.MACHINES[machine]: + set(param, self.MACHINES[machine][param]) + + setOption('OverwriteDomain', 'true') + domainHome = self.domainParentDir + '/' + domainName + print 'Will create Base domain at ' + domainHome + + print 'Writing base domain...' + writeDomain(domainHome) + closeTemplate() + print 'Base domain created at ' + domainHome + return domainHome + + def extendDomain(self, domainHome, db, dbPrefix, dbPassword, exposeAdminT3Channel, t3ChannelPublicAddress, + t3ChannelPort): + print 'Extending domain at ' + domainHome + print 'Database ' + db + readDomain(domainHome) + setOption('AppDir', self.domainParentDir + '/applications') + + print 'ExposeAdminT3Channel %s with %s:%s ' % (exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) + if 'true' == exposeAdminT3Channel: + self.enable_admin_channel(t3ChannelPublicAddress, t3ChannelPort) + + print 'Applying JRF templates...' + for extensionTemplate in self.JRF_12214_TEMPLATES['extensionTemplates']: + addTemplate(self.replaceTokens(extensionTemplate)) + + print 'Applying WCPortal templates...' + for extensionTemplate in self.WCPortal_12214_TEMPLATES['extensionTemplates']: + addTemplate(self.replaceTokens(extensionTemplate)) + + print 'Extension Templates added...' + + cd('/') + delete('WC_Portal', 'Server') + print 'WC_Portal Managed server deleted...' + + self.configureJDBCTemplates(db, dbPrefix, dbPassword) + + print 'Targeting Server Groups...' + serverGroupsToTarget = list(self.JRF_12214_TEMPLATES['serverGroupsToTarget']) + serverGroupsToTarget.extend(self.WCPortal_12214_TEMPLATES['serverGroupsToTarget']) + self.targetWCPServers(serverGroupsToTarget) + + print 'Targeting Cluster ...' + + cd('/') + print "Set CoherenceClusterSystemResource to defaultCoherenceCluster for cluster:" + clusterName + cd('/Cluster/' + clusterName) + set('CoherenceClusterSystemResource', 'defaultCoherenceCluster') + + print "Set WLS clusters as target of defaultCoherenceCluster:" + clusterName + cd('/CoherenceClusterSystemResource/defaultCoherenceCluster') + set('Target', clusterName) + + print 'Preparing to update domain...' + updateDomain() + print 'Domain updated successfully' + closeDomain() + return + + + ########################################################################### + # Helper Methods # + ########################################################################### + + def createManagedServers(self, ms_count, managedNameBase, ms_port, ms_sslport, cluster_name, ms_servers, sslEnabled): + # Create managed servers + for index in range(0, ms_count): + cd('/') + msIndex = index+1 + cd('/') + name = '%s%s' % (managedNameBase, msIndex) + create(name, 'Server') + cd('/Servers/%s/' % name ) + print('managed server name is %s' % name); + set('ListenPort', ms_port) + set('NumOfRetriesBeforeMSIMode', 0) + set('RetryIntervalBeforeMSIMode', 1) + set('Cluster', cluster_name) + cmo.setWeblogicPluginEnabled(true) + ms_servers.append(name) + if (sslEnabled == 'true'): + print 'Enabling SSL for Managed server...' + create(name, 'SSL') + cd('/Servers/' + name+ '/SSL/' + name) + set('ListenPort', ms_sslport) + set('Enabled', 'True') + print ms_servers + return ms_servers + + def targetWCPServers(self, serverGroupsToTarget): + for managedName in self.MANAGED_SERVERS: + setServerGroups(managedName, serverGroupsToTarget) + print "Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:" + managedName + cd('/Servers/' + managedName) + set('CoherenceClusterSystemResource', 'defaultCoherenceCluster') + return + + def configureJDBCTemplates(self, db, dbPrefix, dbPassword): + print 'Configuring the Service Table DataSource...' + fmwDb = 'jdbc:oracle:thin:@' + db + print 'fmwDatabase ' + fmwDb + cd('/JDBCSystemResource/LocalSvcTblDataSource/JdbcResource/LocalSvcTblDataSource') + cd('JDBCDriverParams/NO_NAME_0') + set('DriverName', 'oracle.jdbc.OracleDriver') + set('URL', fmwDb) + set('PasswordEncrypted', dbPassword) + + cd('Properties/NO_NAME_0') + create('oracle.jdbc.fanEnabled', 'Property') + cd('Property') + cd('oracle.jdbc.fanEnabled') + set('Value', 'false') + cd('../../../..') + + stbUser = dbPrefix + '_STB' + cd('Properties/NO_NAME_0/Property/user') + set('Value', stbUser) + + print 'Getting Database Defaults...' + getDatabaseDefaults() + return + + def validateDirectory(self, dirName, create=False): + directory = os.path.realpath(dirName) + if not os.path.exists(directory): + if create: + os.makedirs(directory) + else: + message = 'Directory ' + directory + ' does not exist' + raise WLSTException(message) + elif not os.path.isdir(directory): + message = 'Directory ' + directory + ' is not a directory' + raise WLSTException(message) + return self.fixupPath(directory) + + + def fixupPath(self, path): + result = path + if path is not None: + result = path.replace('\\', '/') + return result + + + def replaceTokens(self, path): + result = path + if path is not None: + result = path.replace('@@ORACLE_HOME@@', oracleHome) + return result + + def enable_admin_channel(self, admin_channel_address, admin_channel_port): + if admin_channel_address == None or admin_channel_port == 'None': + return + cd('/') + admin_server_name = get('AdminServerName') + print('setting admin server t3channel for ' + admin_server_name) + cd('/Servers/' + admin_server_name) + create('T3Channel', 'NetworkAccessPoint') + cd('/Servers/' + admin_server_name + '/NetworkAccessPoint/T3Channel') + set('ListenPort', int(admin_channel_port)) + set('PublicPort', int(admin_channel_port)) + set('PublicAddress', admin_channel_address) + +############################# +# Entry point to the script # +############################# + +def usage(): + print sys.argv[0] + ' -oh -jh -parent -name ' + \ + '-user -password ' + \ + '-rcuDb -rcuPrefix -rcuSchemaPwd ' \ + '-adminListenPort -adminName ' \ + '-managedNameBase -managedServerPort -prodMode ' \ + '-managedServerCount -clusterName ' \ + '-exposeAdminT3Channel -t3ChannelPublicAddress
' \ + '-t3ChannelPort ' + sys.exit(0) + +# Uncomment for Debug only +#print str(sys.argv[0]) + " called with the following sys.argv array:" +#for index, arg in enumerate(sys.argv): +# print "sys.argv[" + str(index) + "] = " + str(sys.argv[index]) + +if len(sys.argv) < 16: + usage() + +#oracleHome will be passed by command line parameter -oh. +oracleHome = None +#javaHome will be passed by command line parameter -jh. +javaHome = None +#domainParentDir will be passed by command line parameter -parent. +domainParentDir = None +#domainUser is hard-coded to weblogic. You can change to other name of your choice. Command line paramter -user. +domainUser = 'weblogic' +#domainPassword will be passed by Command line parameter -password. +domainPassword = None +#rcuDb will be passed by command line parameter -rcuDb. +rcuDb = None +#change rcuSchemaPrefix to your infra schema prefix. Command line parameter -rcuPrefix. +rcuSchemaPrefix = 'DEV12' +#change rcuSchemaPassword to your infra schema password. Command line parameter -rcuSchemaPwd. +rcuSchemaPassword = None +exposeAdminT3Channel = None +t3ChannelPort = None +t3ChannelPublicAddress = None +i = 1 +while i < len(sys.argv): + if sys.argv[i] == '-oh': + oracleHome = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-jh': + javaHome = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-parent': + domainParentDir = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-name': + domainName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-user': + domainUser = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-password': + domainPassword = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuDb': + rcuDb = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuPrefix': + rcuSchemaPrefix = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuSchemaPwd': + rcuSchemaPassword = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-adminListenPort': + adminListenPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-adminServerSSLPort': + adminServerSSLPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-adminName': + adminName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedNameBase': + managedNameBase = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedServerPort': + managedServerPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedServerSSLPort': + managedServerSSLPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-prodMode': + prodMode = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedServerCount': + managedCount = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-clusterName': + clusterName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-t3ChannelPublicAddress': + t3ChannelPublicAddress = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-t3ChannelPort': + t3ChannelPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-exposeAdminT3Channel': + exposeAdminT3Channel = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-sslEnabled': + sslEnabled = sys.argv[i + 1] + i += 2 + else: + print 'Unexpected argument switch at position ' + str(i) + ': ' + str(sys.argv[i]) + usage() + sys.exit(1) + +provisioner = WCPortal12214Provisioner(oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName) +provisioner.createWCPortalDomain(domainName, domainUser, domainPassword, rcuDb, rcuSchemaPrefix, rcuSchemaPassword, + adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, + clusterName, sslEnabled, adminServerSSLPort, managedServerSSLPort, exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/utility.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/utility.sh new file mode 100755 index 000000000..7d356986d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/utility.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# +# Report an error and fail the job +# $1 - text of error +function fail { + echo ERROR: $1 + exit 1 +} + +# +# Create a folder +# $1 - path of folder to create +function createFolder { + mkdir -m 777 -p $1 + if [ ! -d $1 ]; then + fail "Unable to create folder $1" + fi +} + +function checkCreateDomainScript { + if [ -f $1 ]; then + echo The domain will be created using the script $1 + else + fail "Could not locate the domain creation script ${1}" + fi +} + +function checkDomainSecret { + + # Validate the domain secrets exist before proceeding. + if [ ! -f /weblogic-operator/secrets/username ]; then + fail "The domain secret /weblogic-operator/secrets/username was not found" + fi + if [ ! -f /weblogic-operator/secrets/password ]; then + fail "The domain secret /weblogic-operator/secrets/password was not found" + fi +} + +function prepareDomainHomeDir { + # Do not proceed if the domain already exists + local domainFolder=${DOMAIN_HOME_DIR} + if [ -d ${domainFolder} ]; then + fail "The create domain job will not overwrite an existing domain. The domain folder ${domainFolder} already exists" + fi + + # Create the base folders + createFolder ${DOMAIN_ROOT_DIR}/domains + createFolder ${DOMAIN_LOGS_DIR} + createFolder ${DOMAIN_ROOT_DIR}/applications + createFolder ${DOMAIN_ROOT_DIR}/stores +} + diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml new file mode 100755 index 000000000..ca3fbbdbb --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml @@ -0,0 +1,197 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# The version of this inputs file. Do not modify. +version: create-weblogic-sample-domain-inputs-v1 + +# SSL is disabled by default. Select true to enable SSL. +sslEnabled: false + +# Port number for admin server +adminPort: 7001 + +# SSL Port number for admin server +adminServerSSLPort: 7002 + +# Name of the Admin Server +adminServerName: AdminServer + +# Unique ID identifying a domain. +# This ID must not contain an underscore ("_"), and must be lowercase and unique across all domains in a Kubernetes cluster. +domainUID: wcp-domain + +# Home of the WebLogic domain +# If not specified, the value is derived from the domainUID as /shared/domains/ +domainHome: /u01/oracle/user_projects/domains/$domainUID + +# Determines which WebLogic Servers the operator will start up +# Legal values are "NEVER", "IF_NEEDED", or "ADMIN_ONLY" +serverStartPolicy: IF_NEEDED + +# Cluster name +clusterName: wcp-cluster + +# Number of managed servers to generate for the domain +configuredManagedServerCount: 5 + +# Number of managed servers to initially start for the domain +initialManagedServerReplicas: 2 + +# Base string used to generate managed server names +managedServerNameBase: wcpserver + +# Port number for each managed server +managedServerPort: 8888 + +# SSL Port number for each managed server +managedServerSSLPort: 8889 + +# WebCenter Portal Docker image. +# To build WebCenter Portal images refer https://oracle.github.io/fmw-kubernetes/wcportal-domains/installguide/prepare-your-environment/#build-oracle-webcenter-portal-image +# Update the image according to WebCenter Portal Release version +# For Example : PS4 = oracle/wcportal:12.2.1.4 +# +# Below value is just an sample image name and version +image: oracle/wcportal:12.2.1.4 + +# Image pull policy +# Legal values are "IfNotPresent", "Always", or "Never" +imagePullPolicy: IfNotPresent + +# Name of the Kubernetes secret to access the Docker Store to pull the WebLogic Server Docker image +# The presence of the secret will be validated when this parameter is enabled. +#imagePullSecretName: wcpcsoc1s3cr3t + +# Boolean indicating if production mode is enabled for the domain +productionModeEnabled: true + +# Name of the Kubernetes secret for the Admin Server's username and password +# The name must be lowercase. +# If not specified, the value is derived from the domainUID as -weblogic-credentials +weblogicCredentialsSecretName: wcpinfra-domain-credentials + +# Whether to include server .out to the pod's stdout. +# The default is true. +includeServerOutInPodLog: true + +# The in-pod location for domain log, server logs, server out, and node manager log files +# If not specified, the value is derived from the domainUID as /shared/logs/ +logHome: /u01/oracle/user_projects/domains/logs/$domainUID + +# Set this value to 'false' to have HTTP access log files written to the directory configured in the WebLogic domain home. +# The default is 'true', which means HTTP access log files will be written to the logHome directory. +httpAccessLogInLogHome: true + +# Port for the T3Channel of the NetworkAccessPoint +t3ChannelPort: 30012 + +# Public address for T3Channel of the NetworkAccessPoint. This value should be set to the +# kubernetes server address, which you can get by running "kubectl cluster-info". If this +# value is not set to that address, WLST will not be able to connect from outside the +# kubernetes cluster. +#t3PublicAddress: + +# Boolean to indicate if the channel should be exposed as a service +exposeAdminT3Channel: false + +# NodePort to expose for the admin server +adminNodePort: 30701 + +# Boolean to indicate if the adminNodePort will be exposed +exposeAdminNodePort: false + +# Name of the domain namespace +namespace: wcpns + +# If sslEnabled is set to 'true', then comment out the above javaOptions param and uncomment the below javaOptions line. +# To enable SSL, you need to add -Dweblogic.ssl.Enabled=true -Dweblogic.security.SSL.ignoreHostnameVerification=true if sslEnabled is true. +# The reason is the WebLogic generated Demo certificate's host name is different from that of the runtime container. +#javaOptions: -Dweblogic.StdoutDebugEnabled=false -Dweblogic.ssl.Enabled=true -Dweblogic.security.SSL.ignoreHostnameVerification=true + + +#Java Option for WebLogic Server +javaOptions: -Dweblogic.StdoutDebugEnabled=false + +# Name of the persistent volume claim +# If not specified, the value is derived from the domainUID as -weblogic-sample-pvc +persistentVolumeClaimName: wcp-domain-domain-pvc + +# Mount path of the domain persistent volume. +domainPVMountPath: /u01/oracle/user_projects/domains + +# Mount path where the create domain scripts are located inside a pod +# +# The `create-domain.sh` script creates a Kubernetes job to run the script (specified in the +# `createDomainScriptName` property) in a Kubernetes pod to create a WebLogic home. Files +# in the `createDomainFilesDir` directory are mounted to this location in the pod, so that +# a Kubernetes pod can use the scripts and supporting files to create a domain home. +createDomainScriptsMountPath: /u01/weblogic + +# Script that the create domain script uses to create a WebLogic domain +# +# The `create-domain.sh` script creates a Kubernetes job to run this script to create a +# domain home. The script is located in the in-pod directory that is specified in the +# `createDomainScriptsMountPath` property. +# +# If you need to provide your own scripts to create the domain home, instead of using the +# built-it scripts, you must use this property to set the name of the script that you want +# the create domain job to run. +createDomainScriptName: create-domain-job.sh + +# Directory on the host machine to locate all the files to create a WebLogic domain +# It contains the script that is specified in the `createDomainScriptName` property. +# +# By default, this directory is set to the relative path `wlst`, and the create script will +# use the built-in WLST offline scripts in the `wlst` directory to create the WebLogic domain. +# It can also be set to the relative path `wdt`, and then the built-in WDT scripts will be +# used instead. +# +# An absolute path is also supported to point to an arbitrary directory in the file system. +# +# The built-in scripts can be replaced by the user-provided scripts or model files as long +# as those files are in the specified directory. Files in this directory are put into a +# Kubernetes config map, which in turn is mounted to the `createDomainScriptsMountPath`, +# so that the Kubernetes pod can use the scripts and supporting files to create a domain home. +createDomainFilesDir: wlst + +# Uncomment and edit value(s) below to specify the maximum amount of +# compute resources allowed, and minimum amount of compute resources +# required for each server pod. +# These are optional. +# Please refer to the kubernetes documentation on Managing Compute +# Resources for Containers for details. +# +# serverPodMemoryRequest: "64Mi" +# serverPodCpuRequest: "250m" +# serverPodMemoryLimit: "1Gi" +# serverPodCpuLimit: "1000m" + +# +# RCU configuration details +# + +# The schema prefix to use in the database, for example `WCP1`. You may wish to make this +# the same as the domainUID in order to simplify matching domains to their RCU schemas. +rcuSchemaPrefix: WCP1 + +# The database URL +rcuDatabaseURL: dbhostname:dbport/servicename + +# The kubernetes secret containing the database credentials +rcuCredentialsSecret: wcpinfra-rcu-credentials + +# Provide LoadBalancer Hostname +loadBalancerHostName: mycompany.mydomain.com + +# Provide LoadBalancer Port +loadBalancerPortNumber: 30305 + +# Provide LoadBalancer Protocol +loadBalancerProtocol: http + +# Provide LoadBalancer Type +# Legal values are "traefik" or "" +loadBalancerType: traefik + +#Provide unicast port +unicastPort: 50000 diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-job-template.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-job-template.yaml new file mode 100755 index 000000000..a7960ef08 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-job-template.yaml @@ -0,0 +1,98 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +apiVersion: batch/v1 +kind: Job +metadata: + name: %DOMAIN_UID%-create-wcp-infra-sample-domain-job + namespace: %NAMESPACE% +spec: + template: + metadata: + labels: + weblogic.resourceVersion: domain-v2 + weblogic.domainUID: %DOMAIN_UID% + weblogic.domainName: %DOMAIN_NAME% + app: %DOMAIN_UID%-create-wcp-infra-sample-domain-job + spec: + restartPolicy: Never + containers: + - name: create-wcp-infra-sample-domain-job + image: %WEBLOGIC_IMAGE% + imagePullPolicy: %WEBLOGIC_IMAGE_PULL_POLICY% + ports: + - containerPort: 7001 + volumeMounts: + - mountPath: %CREATE_DOMAIN_SCRIPT_DIR% + name: create-wcp-infra-sample-domain-job-cm-volume + - mountPath: %DOMAIN_ROOT_DIR% + name: wcp-infra-sample-domain-storage-volume + - mountPath: /weblogic-operator/secrets + name: wcp-infra-credentials-volume + - mountPath: /weblogic-operator/rcu-secrets + name: rcu-credentials-volume + command: ["/bin/sh"] + args: ["%CREATE_DOMAIN_SCRIPT_DIR%/%CREATE_DOMAIN_SCRIPT%"] + env: + - name: DOMAIN_UID + value: "%DOMAIN_UID%" + - name: ADMIN_SERVER_NAME_SVC + value: "%ADMIN_SERVER_NAME_SVC%" + - name: T3_CHANNEL_PORT + value: "%T3_CHANNEL_PORT%" + - name: T3_PUBLIC_ADDRESS + value: "%T3_PUBLIC_ADDRESS%" + - name: MANAGED_SERVER_NAME_BASE_SVC + value: "%MANAGED_SERVER_NAME_BASE_SVC%" + - name: CREATE_DOMAIN_SCRIPT_DIR + value: "%CREATE_DOMAIN_SCRIPT_DIR%" + - name: DOMAIN_ROOT_DIR + value: "%DOMAIN_ROOT_DIR%" + - name: DOMAIN_HOME_DIR + value: "%DOMAIN_HOME%" + - name: DOMAIN_LOGS_DIR + value: "%DOMAIN_ROOT_DIR%/logs/%DOMAIN_UID%" + - name: CUSTOM_DOMAIN_NAME + value: "%DOMAIN_NAME%" + - name: CUSTOM_ADMIN_LISTEN_PORT + value: "%ADMIN_PORT%" + - name: CUSTOM_ADMIN_NAME + value: "%ADMIN_SERVER_NAME%" + - name: CUSTOM_ADMIN_HOST + value: "%CUSTOM_ADMIN_HOST%" + - name: CUSTOM_MANAGEDSERVER_PORT + value: "%MANAGED_SERVER_PORT%" + - name: CUSTOM_MANAGED_BASE_NAME + value: "%MANAGED_SERVER_NAME_BASE%" + - name: CUSTOM_MANAGED_SERVER_COUNT + value: "%CONFIGURED_MANAGED_SERVER_COUNT%" + - name: CUSTOM_CLUSTER_NAME + value: "%CLUSTER_NAME%" + - name: CUSTOM_RCUPREFIX + value: "%CUSTOM_RCUPREFIX%" + - name: CUSTOM_PRODUCTION_MODE + value: "%PRODUCTION_MODE_ENABLED%" + - name: CUSTOM_CONNECTION_STRING + value: "%CUSTOM_CONNECTION_STRING%" + - name: EXPOSE_T3_CHANNEL_PREFIX + value: "%EXPOSE_T3_CHANNEL_PREFIX%" + - name: SSL_ENABLED + value: "%SSL_ENABLED%" + - name: ADMIN_SERVER_SSL_PORT + value: "%ADMIN_SERVER_SSL_PORT%" + - name: MANAGED_SERVER_SSL_PORT + value: "%MANAGED_SERVER_SSL_PORT%" + volumes: + - name: create-wcp-infra-sample-domain-job-cm-volume + configMap: + name: %DOMAIN_UID%-create-wcp-infra-sample-domain-job-cm + - name: wcp-infra-sample-domain-storage-volume + persistentVolumeClaim: + claimName: %DOMAIN_PVC_NAME% + - name: wcp-infra-credentials-volume + secret: + secretName: %WEBLOGIC_CREDENTIALS_SECRET_NAME% + - name: rcu-credentials-volume + secret: + secretName: %RCU_CREDENTIALS_SECRET_NAME% + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%imagePullSecrets: + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%- name: %WEBLOGIC_IMAGE_PULL_SECRET_NAME% diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain.sh new file mode 100755 index 000000000..ebbd5cca5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain.sh @@ -0,0 +1,292 @@ +#!/usr/bin/env bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description +# This sample script creates a Fusion Middleware Infrastructure domain home on an existing PV/PVC, +# and generates the domain resource yaml file, which can be used to restart the Kubernetes artifacts +# of the corresponding domain. +# +# The domain creation inputs can be customized by editing create-domain-inputs.yaml +# +# The following pre-requisites must be handled prior to running this script: +# * The kubernetes namespace must already be created +# * The kubernetes secrets 'username' and 'password' of the admin account have been created in the namespace +# * The host directory that will be used as the persistent volume must already exist +# and have the appropriate file permissions set. +# * The kubernetes persistent volume must already be created +# * The kubernetes persistent volume claim must already be created +# + +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/../../common/utility.sh +source ${scriptDir}/../../common/validate.sh + +function usage { + echo usage: ${script} -o dir -i file [-e] [-v] [-t timeout] [-h] + echo " -i Parameter inputs file, must be specified." + echo " -o Output directory for the generated yaml files, must be specified." + echo " -e Also create the resources in the generated yaml files, optional." + echo " -v Validate the existence of persistentVolumeClaim, optional." + echo " -t Timeout (in seconds) for create domain job execution, optional." + echo " -h Help" + exit $1 +} + +# +# Parse the command line options +# +doValidation=false +executeIt=false +timeout=600 +while getopts "evhi:o:t:" opt; do + case $opt in + i) valuesInputFile="${OPTARG}" + ;; + o) outputDir="${OPTARG}" + ;; + v) doValidation=true + ;; + e) executeIt=true + ;; + t) timeout="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${valuesInputFile} ]; then + echo "${script}: -i must be specified." + missingRequiredOption="true" +fi + +if [ -z ${outputDir} ]; then + echo "${script}: -o must be specified." + missingRequiredOption="true" +fi + +if [ "${missingRequiredOption}" == "true" ]; then + usage 1 +fi + +if [ -z ${timeout} ]; then + timeout=600 +fi + +# +# Function to initialize and validate the output directory +# for the generated yaml files for this domain. +# +function initOutputDir { + domainOutputDir="${outputDir}/weblogic-domains/${domainUID}" + # Create a directory for this domain's output files + mkdir -p ${domainOutputDir} + + removeFileIfExists ${domainOutputDir}/${valuesInputFile} + removeFileIfExists ${domainOutputDir}/create-domain-inputs.yaml + removeFileIfExists ${domainOutputDir}/create-domain-job.yaml + removeFileIfExists ${domainOutputDir}/delete-domain-job.yaml + removeFileIfExists ${domainOutputDir}/domain.yaml +} + +# +# Function to setup the environment to run the create domain job +# +function initialize { + + # Validate the required files exist + validateErrors=false + + validateKubectlAvailable + + if [ -z "${valuesInputFile}" ]; then + validationError "You must use the -i option to specify the name of the inputs parameter file (a modified copy of kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml)." + else + if [ ! -f ${valuesInputFile} ]; then + validationError "Unable to locate the input parameters file ${valuesInputFile}" + fi + fi + + if [ -z "${outputDir}" ]; then + validationError "You must use the -o option to specify the name of an existing directory to store the generated yaml files in." + fi + + createJobInput="${scriptDir}/create-domain-job-template.yaml" + if [ ! -f ${createJobInput} ]; then + validationError "The template file ${createJobInput} for creating a WebLogic domain was not found" + fi + + deleteJobInput="${scriptDir}/delete-domain-job-template.yaml" + if [ ! -f ${deleteJobInput} ]; then + validationError "The template file ${deleteJobInput} for deleting a WebLogic domain was not found" + fi + + dcrInput="${scriptDir}/../../common/jrf-domain-template.yaml" + if [ ! -f ${dcrInput} ]; then + validationError "The template file ${dcrInput} for creating the domain resource was not found" + fi + + failIfValidationErrors + + validateCommonInputs + + initOutputDir + getKubernetesClusterIP + if [ -z "${t3PublicAddress}" ]; then + t3PublicAddress="${K8S_IP}" + fi +} + +# create domain configmap using what is in the createDomainFilesDir +function createDomainConfigmap { + # Use the default files if createDomainFilesDir is not specified + if [ -z "${createDomainFilesDir}" ]; then + createDomainFilesDir=${scriptDir}/wlst + elif [[ ! ${createDomainFilesDir} == /* ]]; then + createDomainFilesDir=${scriptDir}/${createDomainFilesDir} + fi + + # customize the files with domain information + externalFilesTmpDir=$domainOutputDir/tmp + mkdir -p $externalFilesTmpDir + cp ${createDomainFilesDir}/* ${externalFilesTmpDir}/ + if [ -d "${scriptDir}/common" ]; then + cp ${scriptDir}/common/* ${externalFilesTmpDir}/ + fi + cp ${domainOutputDir}/create-domain-inputs.yaml ${externalFilesTmpDir}/ + + # Set the domainName in the inputs file that is contained in the configmap. + # this inputs file can be used by the scripts, such as WDT, that creates the WebLogic + # domain in the job. + echo domainName: $domainName >> ${externalFilesTmpDir}/create-domain-inputs.yaml + + if [ -f ${externalFilesTmpDir}/prepare.sh ]; then + bash ${externalFilesTmpDir}/prepare.sh -i ${externalFilesTmpDir} + fi + + # create the configmap and label it properly + local cmName=${domainUID}-create-wcp-infra-sample-domain-job-cm + kubectl create configmap ${cmName} -n $namespace --from-file $externalFilesTmpDir + + echo Checking the configmap $cmName was created + local num=`kubectl get cm -n $namespace | grep ${cmName} | wc | awk ' { print $1; } '` + if [ "$num" != "1" ]; then + fail "The configmap ${cmName} was not created" + fi + + kubectl label configmap ${cmName} -n $namespace weblogic.resourceVersion=domain-v2 weblogic.domainUID=$domainUID weblogic.domainName=$domainName + + rm -rf $externalFilesTmpDir +} + +# +# Function to run the job that creates the domain +# +function createDomainHome { + + # create the config map for the job + createDomainConfigmap + + # There is no way to re-run a kubernetes job, so first delete any prior job + CONTAINER_NAME="create-wcp-infra-sample-domain-job" + JOB_NAME="${domainUID}-${CONTAINER_NAME}" + deleteK8sObj job $JOB_NAME ${createJobOutput} + #Traefik Session Setting + if [ -z "$loadBalancerType" ] + then + echo "\$loadBalancerType is empty" + else + echo "\$loadBalancerType is NOT empty" + if (( $loadBalancerType == "traefik" )) ; then + export LB_SETTINGS="\ clusterService:\n\ + annotations: \n\ + traefik.ingress.kubernetes.io/service.sticky.cookie: \"true\"\n\ + traefik.ingress.kubernetes.io/service.sticky.cookie.name: wcpsticky" + sed -i -e "/clusterName: ${clusterName}/a ${LB_SETTINGS}" ${dcrOutput} + fi + fi + #Replacing LoadBalancer parameters in script file. + sed -i -e "s:%LOAD_BALANCER_HOSTNAME%:${loadBalancerHostName}:g" ${createJobOutput} + sed -i -e "s:%LOAD_BALANCER_PORTNUMBER%:${loadBalancerPortNumber}:g" ${createJobOutput} + sed -i -e "s:%LOAD_BALANCER_PROTOCOL%:${loadBalancerProtocol}:g" ${createJobOutput} + sed -i -e "s:%UNICAST_PORTNUMBER%:${unicastPort}:g" ${createJobOutput} + echo Creating the domain by creating the job ${createJobOutput} + kubectl create -f ${createJobOutput} + + echo "Waiting for the job to complete..." + JOB_STATUS="0" + max=`expr ${timeout} / 30` + count=0 + while [ "$JOB_STATUS" != "Completed" -a $count -lt $max ] ; do + sleep 30 + count=`expr $count + 1` + JOBS=`kubectl get pods -n ${namespace} | grep ${JOB_NAME}` + JOB_ERRORS=`kubectl logs jobs/$JOB_NAME $CONTAINER_NAME -n ${namespace} | grep "ERROR:" ` + JOB_STATUS=`echo $JOBS | awk ' { print $3; } '` + JOB_INFO=`echo $JOBS | awk ' { print "pod", $1, "status is", $3; } '` + echo "status on iteration $count of $max" + echo "$JOB_INFO" + + # Terminate the retry loop when a fatal error has already occurred. Search for "ERROR:" in the job log file + if [ "$JOB_STATUS" != "Completed" ]; then + ERR_COUNT=`echo $JOB_ERRORS | grep "ERROR:" | wc | awk ' {print $1; }'` + if [ "$ERR_COUNT" != "0" ]; then + echo "A failure was detected in the log file for job $JOB_NAME." + echo "$JOB_ERRORS" + echo "Check the log output for additional information." + fail "Exiting due to failure - the job has failed!" + fi + fi + done + + # Confirm the job pod is status completed + if [ "$JOB_STATUS" != "Completed" ]; then + echo "The create domain job is not showing status completed after waiting 300 seconds." + echo "Check the log output for errors." + kubectl logs jobs/$JOB_NAME $CONTAINER_NAME -n ${namespace} + fail "Exiting due to failure - the job status is not Completed!" + fi + + # Check for successful completion in log file + JOB_POD=`kubectl get pods -n ${namespace} | grep ${JOB_NAME} | awk ' { print $1; } '` + JOB_STS=`kubectl logs $JOB_POD $CONTAINER_NAME -n ${namespace} | grep "Successfully Completed" | awk ' { print $1; } '` + if [ "${JOB_STS}" != "Successfully" ]; then + echo The log file for the create domain job does not contain a successful completion status + echo Check the log output for errors + kubectl logs $JOB_POD $CONTAINER_NAME -n ${namespace} + fail "Exiting due to failure - the job log file does not contain a successful completion status!" + fi +} + +# +# Function to output to the console a summary of the work completed +# +function printSummary { + + # Get the IP address of the kubernetes cluster (into K8S_IP) + getKubernetesClusterIP + + echo "" + echo "Domain ${domainName} was created and will be started by the WebLogic Kubernetes Operator" + echo "" + if [ "${exposeAdminNodePort}" = true ]; then + echo "Administration console access is available at http://${K8S_IP}:${adminNodePort}/console" + fi + if [ "${exposeAdminT3Channel}" = true ]; then + echo "T3 access is available at t3://${K8S_IP}:${t3ChannelPort}" + fi + echo "The following files were generated:" + echo " ${domainOutputDir}/create-domain-inputs.yaml" + echo " ${createJobOutput}" + echo " ${dcrOutput}" + echo "" + echo "Completed" +} + +# Perform the sequence of steps to create a domain +createDomain false diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/delete-domain-job-template.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/delete-domain-job-template.yaml new file mode 100755 index 000000000..32e2bf2a3 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/delete-domain-job-template.yaml @@ -0,0 +1,62 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +apiVersion: v1 +kind: ConfigMap +metadata: + name: %DOMAIN_UID%-delete-wcp-infra-sample-domain-job-cm + namespace: %NAMESPACE% + labels: + weblogic.resourceVersion: domain-v2 + weblogic.domainUID: %DOMAIN_UID% + weblogic.domainName: %DOMAIN_NAME% +data: + delete-domain-job.sh: |- + #!/bin/bash + # + # delete domainHome folder + rm -rf ${DOMAIN_HOME_DIR} + + echo "Delete Completed" +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: %DOMAIN_UID%-delete-wcp-infra-sample-domain-job + namespace: %NAMESPACE% +spec: + template: + metadata: + labels: + weblogic.resourceVersion: domain-v2 + weblogic.domainUID: %DOMAIN_UID% + weblogic.domainName: %DOMAIN_NAME% + app: %DOMAIN_UID%-delete-wcp-infra-sample-domain-job + spec: + restartPolicy: Never + containers: + - name: delete-wcp-infra-sample-domain-job + image: %WEBLOGIC_IMAGE% + imagePullPolicy: IfNotPresent + ports: + - containerPort: 7001 + volumeMounts: + - mountPath: /u01/weblogic + name: delete-wcp-infra-sample-domain-job-cm-volume + - mountPath: %DOMAIN_ROOT_DIR% + name: wcp-infra-sample-domain-storage-volume + command: ["/bin/sh"] + args: ["/u01/weblogic/delete-domain-job.sh"] + env: + - name: DOMAIN_HOME_DIR + value: %DOMAIN_HOME% + - name: DOMAIN_LOGS_DIR + value: %DOMAIN_ROOT_DIR%/logs/%DOMAIN_UID% + volumes: + - name: delete-wcp-infra-sample-domain-job-cm-volume + configMap: + name: %DOMAIN_UID%-delete-wcp-infra-sample-domain-job-cm + - name: wcp-infra-sample-domain-storage-volume + persistentVolumeClaim: + claimName: %DOMAIN_PVC_NAME% + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%imagePullSecrets: + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%- name: %WEBLOGIC_IMAGE_PULL_SECRET_NAME% diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/wlst/create-domain-script.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/wlst/create-domain-script.sh new file mode 100755 index 000000000..ce12c4e0d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/wlst/create-domain-script.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Copyright (c) 2021 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +export DOMAIN_HOME=${DOMAIN_HOME_DIR} + +if [ -z "${JAVA_HOME}" ]; then + JAVA_HOME=/usr/java/latest +fi + +# Create the domain +wlst.sh -skipWLSModuleScanning \ + ${CREATE_DOMAIN_SCRIPT_DIR}/createWebCenterPortalDomain.py \ + -oh /u01/oracle \ + -jh ${JAVA_HOME} \ + -parent ${DOMAIN_HOME}/.. \ + -name ${CUSTOM_DOMAIN_NAME} \ + -user `cat /weblogic-operator/secrets/username` \ + -password `cat /weblogic-operator/secrets/password` \ + -rcuDb ${CUSTOM_CONNECTION_STRING} \ + -rcuPrefix ${CUSTOM_RCUPREFIX} \ + -rcuSchemaPwd `cat /weblogic-operator/rcu-secrets/password` \ + -adminListenPort ${CUSTOM_ADMIN_LISTEN_PORT} \ + -adminName ${CUSTOM_ADMIN_NAME} \ + -managedNameBase ${CUSTOM_MANAGED_BASE_NAME} \ + -managedServerPort ${CUSTOM_MANAGEDSERVER_PORT} \ + -prodMode ${CUSTOM_PRODUCTION_MODE} \ + -managedServerCount ${CUSTOM_MANAGED_SERVER_COUNT} \ + -clusterName ${CUSTOM_CLUSTER_NAME} \ + -exposeAdminT3Channel ${EXPOSE_T3_CHANNEL_PREFIX} \ + -t3ChannelPublicAddress ${T3_PUBLIC_ADDRESS} \ + -sslEnabled ${SSL_ENABLED} \ + -adminServerSSLPort ${ADMIN_SERVER_SSL_PORT} \ + -managedServerSSLPort ${MANAGED_SERVER_SSL_PORT} \ + -t3ChannelPort ${T3_CHANNEL_PORT} diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml new file mode 100755 index 000000000..5c9e711f9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +weblogicLoggingIndexName: wls +publishHost: elasticsearch.wcpns.svc.cluster.local +publishPort: 9600 +domainUID: wcp-domain +weblogicLoggingExporterEnabled: true +weblogicLoggingExporterSeverity: TRACE +weblogicLoggingExporterBulkSize: 1 diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_as.yml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_as.yml new file mode 100755 index 000000000..df8248388 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_as.yml @@ -0,0 +1,63 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +metricsNameSnakeCase: true +restPort: 7001 +queries: +- key: name + keyName: location + prefix: wls_server_ + applicationRuntimes: + key: name + keyName: app + componentRuntimes: + prefix: wls_webapp_config_ + type: WebAppComponentRuntime + key: name + values: [deploymentState, contextRoot, sourceInfo, openSessionsHighCount, openSessionsCurrentCount, sessionsOpenedTotalCount, sessionCookieMaxAgeSecs, sessionInvalidationIntervalSecs, sessionTimeoutSecs, singleThreadedServletPoolSize, sessionIDLength, servletReloadCheckSecs, jSPPageCheckSecs] + servlets: + prefix: wls_servlet_ + key: servletName + +- JVMRuntime: + prefix: wls_jvm_ + key: name + +- executeQueueRuntimes: + prefix: wls_socketmuxer_ + key: name + values: [pendingRequestCurrentCount] + +- workManagerRuntimes: + prefix: wls_workmanager_ + key: name + values: [stuckThreadCount, pendingRequests, completedRequests] + +- threadPoolRuntime: + prefix: wls_threadpool_ + key: name + values: [executeThreadTotalCount, queueLength, stuckThreadCount, hoggingThreadCount] + +- JMSRuntime: + key: name + keyName: jmsruntime + prefix: wls_jmsruntime_ + JMSServers: + prefix: wls_jms_ + key: name + keyName: jmsserver + destinations: + prefix: wls_jms_dest_ + key: name + keyName: destination + +- persistentStoreRuntimes: + prefix: wls_persistentstore_ + key: name +- JDBCServiceRuntime: + JDBCDataSourceRuntimeMBeans: + prefix: wls_datasource_ + key: name +- JTARuntime: + prefix: wls_jta_ + key: name diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_ms.yml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_ms.yml new file mode 100755 index 000000000..a6e1f113e --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_ms.yml @@ -0,0 +1,63 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +metricsNameSnakeCase: true +restPort: 8888 +queries: +- key: name + keyName: location + prefix: wls_server_ + applicationRuntimes: + key: name + keyName: app + componentRuntimes: + prefix: wls_webapp_config_ + type: WebAppComponentRuntime + key: name + values: [deploymentState, contextRoot, sourceInfo, openSessionsHighCount, openSessionsCurrentCount, sessionsOpenedTotalCount, sessionCookieMaxAgeSecs, sessionInvalidationIntervalSecs, sessionTimeoutSecs, singleThreadedServletPoolSize, sessionIDLength, servletReloadCheckSecs, jSPPageCheckSecs] + servlets: + prefix: wls_servlet_ + key: servletName + +- JVMRuntime: + prefix: wls_jvm_ + key: name + +- executeQueueRuntimes: + prefix: wls_socketmuxer_ + key: name + values: [pendingRequestCurrentCount] + +- workManagerRuntimes: + prefix: wls_workmanager_ + key: name + values: [stuckThreadCount, pendingRequests, completedRequests] + +- threadPoolRuntime: + prefix: wls_threadpool_ + key: name + values: [executeThreadTotalCount, queueLength, stuckThreadCount, hoggingThreadCount] + +- JMSRuntime: + key: name + keyName: jmsruntime + prefix: wls_jmsruntime_ + JMSServers: + prefix: wls_jms_ + key: name + keyName: jmsserver + destinations: + prefix: wls_jms_dest_ + key: name + keyName: destination + +- persistentStoreRuntimes: + prefix: wls_persistentstore_ + key: name +- JDBCServiceRuntime: + JDBCDataSourceRuntimeMBeans: + prefix: wls_datasource_ + key: name +- JTARuntime: + prefix: wls_jta_ + key: name diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/weblogic.xml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/weblogic.xml new file mode 100755 index 000000000..c4e2df0c5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/weblogic.xml @@ -0,0 +1,18 @@ + + + + wls-exporter + + + com.google.gson.* + javax.inject.* + org.apache.commons.* + org.apache.http.* + org.glassfish.hk2.* + org.jvnet.hk2.* + org.jvnet.tiger_types.* + org.yaml.snakeyaml.* + + + + diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/get1.1.0.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/get1.1.0.sh new file mode 100755 index 000000000..5dccd1a71 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/get1.1.0.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +curl -L -O https://github.com/oracle/weblogic-monitoring-exporter/releases/download/v1.1.0/wls-exporter.war + +echo "-------------------wls-exporter-ms start-------------------" +tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX) +mkdir -p $tmp_dir/WEB-INF +echo "created $tmp_dir" + +cp config/config_ms.yml $tmp_dir/config.yml +cp config/weblogic.xml $tmp_dir/WEB-INF/weblogic.xml +echo "Copying completed" + +warDir=$PWD +pushd $tmp_dir + +cp $warDir/wls-exporter.war $warDir/wls-exporter-ms.war +echo "in temp dir" +zip $warDir/wls-exporter-ms.war WEB-INF/weblogic.xml +zip $warDir/wls-exporter-ms.war config.yml +echo "wls-exporter-ms.war is ready" +echo "-------------------wls-exporter-ms end-------------------" + +echo "-------------------wls-exporter-as start-------------------" +cp $warDir/config/config_as.yml $tmp_dir/config.yml +echo "Copying completed" +cp $warDir/wls-exporter.war $warDir/wls-exporter-as.war +echo "in temp dir" +zip $warDir/wls-exporter-as.war WEB-INF/weblogic.xml +zip $warDir/wls-exporter-as.war config.yml +echo "wls-exporter-as.war is ready" +echo "-------------------wls-exporter-as end-------------------" +echo "zip completed" +popd +rm -rf $tmp_dir +rm $warDir/wls-exporter.war diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml new file mode 100755 index 000000000..075afa320 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml @@ -0,0 +1,42 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +apiVersion: v1 +kind: Secret +metadata: + name: basic-auth + namespace: monitoring +data: + password: d2VsY29tZTEK # welcome1 i.e.'WebLogic password' + user: d2VibG9naWM= # weblogic i.e. 'WebLogic username' +type: Opaque +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: wls-exporter-wcp-domain + namespace: monitoring + labels: + k8s-app: wls-exporter +spec: + namespaceSelector: + matchNames: + - wcpns + selector: + matchLabels: + weblogic.domainName: wcp-domain + endpoints: + - basicAuth: + password: + name: basic-auth + key: password + username: + name: basic-auth + key: user + port: default + relabelings: + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + interval: 10s + honorLabels: true + path: /wls-exporter/metrics diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-loadbalancer.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-loadbalancer.yaml new file mode 100755 index 000000000..6d2804479 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-loadbalancer.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +apiVersion: v1 +kind: Service +metadata: + name: es-loadbalancer + namespace: wcpns +spec: + type: LoadBalancer + selector: + service: elasticsearch + ports: + - name: http + port: 9200 + targetPort: 9200 diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-pvpvc.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-pvpvc.yaml new file mode 100755 index 000000000..f5198beb8 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-pvpvc.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +apiVersion: v1 +kind: PersistentVolume +metadata: + name: es-data-pv + namespace: wcpns +spec: + storageClassName: es-data-pv-storage-class + capacity: + storage: 10Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + hostPath: + path: "/scratch/esdata" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: es-data-pvc + namespace: wcpns +spec: + storageClassName: es-data-pv-storage-class + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Gi \ No newline at end of file diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-secret.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-secret.yaml new file mode 100755 index 000000000..676cc1e7d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-secret.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +apiVersion: v1 +kind: Secret +metadata: + name: es-secret + namespace: wcpns +data: + # base64 encoded strings + wls-admin: d2VibG9naWM= + wls-admin-pwd: d2VsY29tZTE= + search-admin: d2NjcmF3bGFkbWlu + search-admin-pwd: d2VsY29tZTE= \ No newline at end of file diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-service.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-service.yaml new file mode 100755 index 000000000..aae18ac5f --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-service.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +apiVersion: v1 +kind: Service +metadata: + name: es-svc + namespace: wcpns + labels: + service: elasticsearch +spec: + # headless service + clusterIP: None + ports: + - port: 9200 + name: http + - port: 9300 + name: transport + selector: + service: elasticsearch \ No newline at end of file diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-statefulset.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-statefulset.yaml new file mode 100755 index 000000000..1af3885b8 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster/es-statefulset.yaml @@ -0,0 +1,114 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: es-statefulset + namespace: wcpns + labels: + service: elasticsearch +spec: + serviceName: es-svc + replicas: 3 + selector: + matchLabels: + service: elasticsearch + template: + metadata: + labels: + service: elasticsearch + spec: + initContainers: + - name: increase-the-vm-max-map-count + image: busybox + command: + - sysctl + - -w + - vm.max_map_count=262144 + securityContext: + privileged: true + - name: increase-the-ulimit + image: busybox + command: + - sh + - -c + - ulimit -n 65536 + securityContext: + privileged: true + volumes: + - name: es-node + persistentVolumeClaim: + claimName: es-data-pvc + - name: wcp-domain + persistentVolumeClaim: + claimName: wcp-domain-domain-pvc + containers: + - name: es-container + image: oracle/wcportal:12.2.1.4 + imagePullPolicy: IfNotPresent + command: [ "/bin/sh", "-c", "/u01/oracle/container-scripts/configureOrStartElasticsearch.sh" ] + readinessProbe: + httpGet: + path: / + port: 9200 + httpHeaders: + - name: Authorization + value: Basic d2NjcmF3bGFkbWluOndlbGNvbWUx + initialDelaySeconds: 150 + periodSeconds: 30 + timeoutSeconds: 10 + successThreshold: 1 + failureThreshold: 10 + lifecycle: + preStop: + exec: + command: [ "/bin/sh", "-c", "/u01/oracle/container-scripts/elasticsearchPreStopHandler.sh" ] + ports: + - containerPort: 9200 + name: http + - containerPort: 9300 + name: tcp + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: UNICAST_HOST_LIST + value: "es-svc" + - name: ADMIN_USERNAME + valueFrom: + secretKeyRef: + name: es-secret + key: wls-admin + - name: ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: es-secret + key: wls-admin-pwd + - name: SEARCH_APP_USERNAME + valueFrom: + secretKeyRef: + name: es-secret + key: search-admin + - name: SEARCH_APP_USER_PASSWORD + valueFrom: + secretKeyRef: + name: es-secret + key: search-admin-pwd + - name: ADMIN_SERVER_CONTAINER_NAME + value: wcp-domain-adminserver + - name: ADMIN_PORT + value: "7001" + - name: ES_CLUSTER_NAME + value: es-cluster + - name: DOMAIN_NAME + value: wcp-domain + - name: CONFIGURE_ES_CONNECTION + value: "true" + - name: LOAD_BALANCER_IP + value: "es-loadbalancer.wcpns.svc.cluster.local" + volumeMounts: + - name: es-node + mountPath: /u01/esHome/esNode + - name: wcp-domain + mountPath: /u01/oracle/user_projects/domains diff --git a/OracleWebCenterPortal/kubernetes/imagetool-scripts/additionalBuildCmds.txt b/OracleWebCenterPortal/kubernetes/imagetool-scripts/additionalBuildCmds.txt new file mode 100755 index 000000000..1a2a3b9be --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/imagetool-scripts/additionalBuildCmds.txt @@ -0,0 +1,30 @@ +[package-manager-packages] +hostname procps sudo zip + +[final-build-commands] + +ENV ORACLE_HOME=/u01/oracle \ + SCRIPT_FILE=/u01/oracle/container-scripts/* \ + USER_MEM_ARGS="-Djava.security.egd=file:/dev/./urandom" \ + PATH=$PATH:/usr/java/default/bin:/u01/oracle/oracle_common/common/bin:/u01/oracle/wlserver/common/bin:/u01/oracle/container-scripts + +USER root + +RUN env && \ + mkdir -p /u01/oracle/container-scripts && \ + mkdir -p /u01/oracle/logs && \ + mkdir -p /u01/esHome/esNode && \ + chown oracle:oracle -R /u01 $VOLUME_DIR && \ + chmod a+xr /u01 + +COPY --chown=oracle:oracle files/container-scripts/ /u01/oracle/container-scripts/ +RUN chmod +xr $SCRIPT_FILE && \ + rm /u01/oracle/oracle_common/lib/ons.jar /u01/oracle/oracle_common/modules/oracle.jdbc/simplefan.jar + +USER oracle +EXPOSE $WCPORTAL_PORT $ADMIN_PORT + +WORKDIR ${ORACLE_HOME} +CMD ["/u01/oracle/container-scripts/configureOrStartAdminServer.sh"] + + diff --git a/OracleWebCenterPortal/kubernetes/imagetool-scripts/buildArgs b/OracleWebCenterPortal/kubernetes/imagetool-scripts/buildArgs new file mode 100755 index 000000000..58be2ac87 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/imagetool-scripts/buildArgs @@ -0,0 +1,10 @@ +create +--jdkVersion=8u281 +--type wcp +--version=12.2.1.4.0 +--tag=oracle/wcportal:12.2.1.4 +--pull +--additionalBuildCommands /docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0/additionalBuildCmds.txt +--additionalBuildFiles /docker-images/OracleWebCenterPortal/dockerfiles/12.2.1.4/container-scripts +--opatchBugNumber 28186730_13.9.4.2.5 +--patches 32253037_12.2.1.4.0,32124456_12.2.1.4.0,32357288_12.2.1.4.0,32224021_12.2.1.4.0,31666198_12.2.1.4.0,31544353_12.2.1.4.0 diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/Chart.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/Chart.yaml new file mode 100755 index 000000000..b42d4f9fa --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/Chart.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart to create an Ingress for a WLS domain. +name: ingress-per-domain +version: 0.1.0 diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/README.md b/OracleWebCenterPortal/kubernetes/ingress-per-domain/README.md new file mode 100644 index 000000000..7b7e89972 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/README.md @@ -0,0 +1,100 @@ +# An Ingress per domain chart +This chart is for deploying an Ingress resource in front of a WebLogic domain cluster. We support three Ingress types: Traefik, Voyager, Nginx. + +## Prerequisites +- Have Docker and a Kubernetes cluster running and have `kubectl` installed and configured. +- Have Helm installed. +- The corresponding Ingress controller, Traefik or Voyager, is installed in the Kubernetes cluster. +- A WebLogic domain cluster deployed by `weblogic-operator` is running in the Kubernetes cluster. + +## Generate Secret to access SSL services + +Command to Generate Secret: +``` +$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" +$ kubectl -n wcpns create secret tls domain1-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + +``` + +## Installing the chart + +To install the chart with the release name, `my-ingress`, with the given `values.yaml`: +``` +# Change directory to the cloned git weblogic-kubernetes-operator repo. +$ cd kubernetes/samples/charts + +# Use helm to install the chart. Use `--namespace` to specify the name of the WebLogic domain's namespace. +$ helm install ingress-per-domain --name my-ingress --namespace my-domain-namespace --values values.yaml +``` +The Ingress resource will be created in the same namespace as the WebLogic domain cluster. + +Sample `values.yaml` for the Traefik Ingress: +``` +type: TRAEFIK + +# WLS domain as backend to the load balancer +wlsDomain: + domainUID: domain1 + clusterName: cluster1 + managedServerPort: 8001 + +# Traefik specific values +traefik: + # hostname used by host-routing + hostname: domain1.org +``` + +Sample `values.yaml` for the Voyager Ingress: +``` +type: VOYAGER + +# WLS domain as backend to the load balancer +wlsDomain: + domainUID: domain1 + clusterName: cluster1 + managedServerPort: 8001 + +# Voyager specific values +voyager: + # web port + webPort: 30305 + # stats port + statsPort: 30315 +``` +Sample `values.yaml` for the NGINX Ingress: +``` +type: NGINX + +# WLS domain as backend to the load balancer +wlsDomain: + domainUID: domain1 + clusterName: cluster1 + managedServerPort: 8001 + +# nginx specific values +nginx: + connectTimeout: 1800 + readTimeout: 1800 + sendTimeout: 1800 + cookieExpires: 172800 + cookieMaxAge: 172800 +``` +## Uninstalling the chart +To uninstall and delete the `my-ingress` deployment: +``` +$ helm delete --purge my-ingress +``` +## Configuration +The following table lists the configurable parameters of this chart and their default values. + +| Parameter | Description | Default | +| --- | --- | --- | +| `type` | Type of Ingress controller. Legal values are `TRAEFIK` or `VOYAGER`. | `TRAEFIK` | +| `wlsDomain.domainUID` | DomainUID of the WLS domain. | `domain1` | +| `wlsDomain.clusterName` | Cluster name in the WLS domain. | `cluster-1` | +| `wlsDomain.managedServerPort` | Port number of the managed servers in the WLS domain cluster. | `8001` | +| `traefik.hostname` | Hostname to route to the WLS domain cluster. | `domain1.org` | +| `voyager.webPort` | Web port to access the Voyager load balancer. | `30305` | +| `voyager.statsPort` | Port to access the Voyager/HAProxy stats page. | `30315` | + +**Note:** The input values `domainUID` and `clusterName` will be used to generate the Kubernetes `serviceName` of the WLS cluster with the format `domainUID-cluster-clusterName`. diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/nginx-ingress.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/nginx-ingress.yaml new file mode 100755 index 000000000..51479d7fe --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/nginx-ingress.yaml @@ -0,0 +1,63 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- if eq .Values.type "NGINX" }} +--- +apiVersion: {{ .Values.apiVersion }} +kind: Ingress +metadata: + name: {{ .Values.wlsDomain.domainUID }}-ingress + namespace: {{ .Release.Namespace }} + annotations: +{{- if eq .Values.tls "SSL" }} + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/configuration-snippet: | + more_set_input_headers "X-Forwarded-Proto: https"; + more_set_input_headers "WL-Proxy-SSL: true"; + nginx.ingress.kubernetes.io/ingress.allow-http: "false" +{{- end }} + nginx.ingress.kubernetes.io/proxy-connect-timeout: "{{ .Values.ngnix.connectTimeout }}" + nginx.ingress.kubernetes.io/proxy-read-timeout: "{{ .Values.ngnix.readTimeout }}" + nginx.ingress.kubernetes.io/proxy-send-timeout: "{{ .Values.ngnix.sendTimeout }}" + nginx.ingress.kubernetes.io/affinity: "cookie" + nginx.ingress.kubernetes.io/session-cookie-name: "stickyid" + nginx.ingress.kubernetes.io/session-cookie-expires: "{{ .Values.ngnix.cookieExpires }}" + nginx.ingress.kubernetes.io/session-cookie-max-age: "{{ .Values.ngnix.cookieMaxAge }}" + nginx.ingress.kubernetes.io/ssl-redirect: "false" + nginx.ingress.kubernetes.io/affinity-mode: persistent +spec: + rules: + - host: '{{ .Values.nginx.hostname }}' + http: + paths: + - path: /webcenter + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /console + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName| lower }}' + servicePort: {{.Values.wlsDomain.adminServerPort}} + - path: /rsscrawl + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /webcenterhelp + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /rest + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /em + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName| lower }}' + servicePort: {{.Values.wlsDomain.adminServerPort}} + {{- if eq .Values.tls "SSL" }} +tls: + - hosts: + - '{{ .Values.nginx.hostname }}' + secretName: domain1-tls-cert +{{- end }} + {{- end }} diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/traefik-ingress.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/traefik-ingress.yaml new file mode 100755 index 000000000..7994e11ff --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/traefik-ingress.yaml @@ -0,0 +1,54 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- if eq .Values.type "TRAEFIK" }} +--- +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ .Values.wlsDomain.domainUID }}-traefik + namespace: {{ .Release.Namespace }} + annotations: + kubernetes.io/ingress.class: traefik +{{- if eq .Values.tls "SSL" }} + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.middlewares: wcpns-wls-proxy-ssl@kubernetescrd +{{- end }} +spec: + rules: + - host: '{{ .Values.traefik.hostname }}' + http: + paths: + - path: /webcenter + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /console + backend: + serviceName: '{{.Values.wlsDomain.domainUID}}-{{.Values.wlsDomain.adminServerName| lower}}' + servicePort: {{.Values.wlsDomain.adminServerPort}} + - path: /rsscrawl + backend: + serviceName: '{{.Values.wlsDomain.domainUID}}-cluster-{{.Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /webcenterhelp + backend: + serviceName: '{{.Values.wlsDomain.domainUID}}-cluster-{{.Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /rest + backend: + serviceName: '{{.Values.wlsDomain.domainUID}}-cluster-{{.Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /em + backend: + serviceName: '{{.Values.wlsDomain.domainUID}}-{{.Values.wlsDomain.adminServerName| lower}}' + servicePort: {{.Values.wlsDomain.adminServerPort}} + + {{- if eq .Values.tls "SSL" }} + tls: + - hosts: + - '{{ .Values.traefik.hostname }}' + secretName: wcpinfra-tls-cert +{{- end }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/voyager-ingress.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/voyager-ingress.yaml new file mode 100755 index 000000000..69ce7147e --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/voyager-ingress.yaml @@ -0,0 +1,79 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- if eq .Values.type "VOYAGER" }} +--- +apiVersion: voyager.appscode.com/v1beta1 +kind: Ingress +metadata: + name: {{ .Values.wlsDomain.domainUID }}-voyager + namespace: {{ .Release.Namespace }} + annotations: + ingress.appscode.com/type: 'NodePort' + ingress.appscode.com/stats: 'true' + ingress.appscode.com/affinity: 'cookie' +spec: +{{- if eq .Values.tls "SSL" }} + frontendRules: + - port: 443 + rules: + - http-request set-header WL-Proxy-SSL true + tls: + - secretName: wcpinfra-tls-cert + hosts: + - '*' +{{- end }} + rules: + - host: '*' + http: + nodePort: '{{ .Values.voyager.webPort }}' + paths: + - path: /webcenter + backend: + serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /console + backend: + serviceName: '{{.Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName| lower}}' + servicePort: {{.Values.wlsDomain.adminServerPort}} + - path: /rsscrawl + backend: + serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /rest + backend: + serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /webcenterhelp + backend: + serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' + servicePort: {{.Values.wlsDomain.managedServerPort}} + - path: /em + backend: + serviceName: '{{.Values.wlsDomain.domainUID}}-{{.Values.wlsDomain.adminServerName| lower}}' + servicePort: {{.Values.wlsDomain.adminServerPort}} +# - path: /wls-exporter +# backend: +# serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' +# servicePort: {{.Values.wlsDomain.managedServerPort}} + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{.Values.wlsDomain.domainUID}}-voyager-stats + namespace: {{.Release.Namespace}} + labels: + weblogic.resourceVersion: domain-v2 +spec: + type: NodePort + ports: + - name: client + protocol: TCP + port: 56789 + targetPort: 56789 + nodePort: {{.Values.voyager.statsPort}} + selector: + origin: voyager + origin-name: {{.Values.wlsDomain.domainUID}}-voyager +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/nginx-tls.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/nginx-tls.yaml new file mode 100755 index 000000000..e34c0bcd9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/nginx-tls.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: wcpns-ingress + namespace: wcpns + annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/ssl-passthrough: "true" +spec: + tls: + - hosts: + - domain1.org + secretName: domain1-tls-cert + rules: + - host: domain1.org + http: + paths: + - path: + backend: + serviceName: wcp-domain-cluster-wcp-cluster + servicePort: 8889 + + diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/traefik-tls.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/traefik-tls.yaml new file mode 100755 index 000000000..96d51a5ab --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/traefik-tls.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteTCP +metadata: + name: wcp-domain-cluster-routetcp + namespace: wcpns +spec: + entryPoints: + - websecure + routes: + - match: HostSNI(`wcp-domain.example.org`) + services: + - name: wcp-domain-cluster-wcp-cluster + port: 8889 + weight: 3 + TerminationDelay: 400 + tls: + passthrough: true \ No newline at end of file diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/voyager-tls.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/voyager-tls.yaml new file mode 100755 index 000000000..dc41c6648 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/voyager-tls.yaml @@ -0,0 +1,27 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +apiVersion: voyager.appscode.com/v1beta1 +kind: Ingress +metadata: + name: voyager-endtoendssl + namespace: wcpns + annotations: + ingress.appscode.com/type: 'NodePort' + ingress.appscode.com/stats: 'true' + ingress.appscode.com/affinity: 'cookie' + ingress.appscode.com/ssl-passthrough: "true" +spec: + tls: + - secretName: domain1-tls-cert + hosts: + - '*' + rules: + - host: '*' + http: + nodePort: '31443' + paths: + - path: / + backend: + serviceName: wcp-domain-cluster-wcp-cluster + servicePort: '8889' diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/values.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/values.yaml new file mode 100755 index 000000000..6a032d868 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/ingress-per-domain/values.yaml @@ -0,0 +1,41 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# Default values for ingress-per-domain. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +apiVersion: networking.k8s.io/v1beta1 + +# Load balancer type. Supported values are: TRAEFIK, VOYAGER ,NGINX +type: TRAEFIK +# Supported values NONSSL ,SSL +tls: NONSSL + +# WLS domain as backend to the load balancer +wlsDomain: + domainUID: wcp-domain + clusterName: wcp-cluster + managedServerPort: 8888 + adminServerPort: 7001 + adminServerName: adminserver + +# Traefik specific values +traefik: + # hostname used by host-routing + hostname: domain1.org + +# Voyager specific values +voyager: + # web port + webPort: 30305 + # stats port + statsPort: 30315 + +# Ngnix specific values +nginx: + connectTimeout: 1800 + readTimeout: 1800 + sendTimeout: 1800 + cookieExpires: 172800 + cookieMaxAge: 172800 diff --git a/README.md b/README.md index 356caf7b5..d2970de7e 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ In addition, we've provided the deployment scripts in this repository to assist - [Oracle SOA Suite](/OracleSOASuite) - [Oracle Unified Directory](/OracleUnifiedDirectory) - [Oracle Unified Directory Services Manager](/OracleUnifiedDirectorySM) + - [Oracle WebCenter Portal](/OracleWebCenterPortal) - [Oracle WebCenter Sites](/OracleWebCenterSites) ## Support diff --git a/docs-source/content/wcportal-domains/_index.md b/docs-source/content/wcportal-domains/_index.md new file mode 100644 index 000000000..a412f1840 --- /dev/null +++ b/docs-source/content/wcportal-domains/_index.md @@ -0,0 +1,45 @@ +--- +title: "Oracle WebCenter Portal" +date: 2021 +weight: 7 +description: "The WebLogic Kubernetes operator (the “operator”) supports deployment of Oracle WebCenter Portal. Follow the instructions in this guide to set up Oracle WebCenter Portal domain on Kubernetes." +--- + + +With the WebLogic Kubernetes operator (operator), you can deploy your Oracle WebCenter Portal on Kubernetes. + +In this release, Oracle WebCenter Portal domain is based on the “domain on a persistent volume” +[model](https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/choosing-a-model/), where the domain home is located in a persistent volume. + +The operator has several key features to assist you with deploying and managing the Oracle WebCenter Portal domain in a Kubernetes environment. You can: + +* Create Oracle WebCenter Portal instances in a Kubernetes PV. This PV can reside in an Network File System (NFS) or other Kubernetes volume types. +* Start servers based on declarative startup parameters and desired states. +* Expose the Oracle WebCenter Portal services for external access. +* Scale Oracle WebCenter Portal domain by starting and stopping Managed Servers on demand, or by integrating with a REST API. +* Publish operator and WebLogic Server logs to Elasticsearch and interact with them in Kibana. +* Monitor the Oracle WebCenter Portal instance using Prometheus and Grafana. +#### Current production release + +The current production release for the Oracle WebCenter Portal domain deployment on Kubernetes is [21.2.1](https://github.com/oracle/fmw-kubernetes/releases). This release uses the WebLogic Kubernetes Operator version [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/releases). + + +#### Recent changes and known issues + +See the [Release Notes]({{< relref "/wcportal-domains/release-notes.md" >}}) for recent changes and known issues with the Oracle WebCenter Portal domain deployment on Kubernetes. + + +#### About this documentation + +This documentation includes sections targeted to different audiences. To help you find what you are looking for more easily, +please use this table of contents: + +* [Quick Start]({{< relref "/wcportal-domains/appendix/quickstart-deployment-on-prem.md" >}}) explains how to quickly get an Oracle WebCenter Portal domain instance running, using the defaults, nothing special. Note that this is only for development and test purposes. +* [Install Guide]({{< relref "/wcportal-domains/installguide" >}}) and [Administration Guide]({{< relref "/wcportal-domains/manage-wcportal-domains/" >}}) provide detailed information about all aspects of using the Kubernetes operator including: + + * Installing and configuring the operator + * Using the operator to create and manage Oracle WebCenter Portal domain + * Configuring WebCenter Portal for Search + * Configuring Kubernetes load balancers + * Configuring Prometheus and Grafana to monitor WebCenter Portal + * Configuring Logging using ElasticSearch diff --git a/docs-source/content/wcportal-domains/appendix/_index.md b/docs-source/content/wcportal-domains/appendix/_index.md new file mode 100644 index 000000000..00ef7b235 --- /dev/null +++ b/docs-source/content/wcportal-domains/appendix/_index.md @@ -0,0 +1,9 @@ ++++ +title = "Appendix" +weight = 6 +pre = "6. " ++++ + +This section provides information on miscellaneous tasks related to the Oracle WebCenter Portal deployment on Kubernetes. + +{{% children style="h4" description="true" %}} diff --git a/docs-source/content/wcportal-domains/appendix/docker-k8s-hardening.md b/docs-source/content/wcportal-domains/appendix/docker-k8s-hardening.md new file mode 100644 index 000000000..73a9065cb --- /dev/null +++ b/docs-source/content/wcportal-domains/appendix/docker-k8s-hardening.md @@ -0,0 +1,26 @@ +--- +title: "Security hardening" +date: 2019-02-22T15:44:42-05:00 +draft: false +weight: 3 +pre : " " +description: "Review resources for the Docker and Kubernetes cluster hardening." +--- + +Securing a Kubernetes cluster involves hardening on multiple fronts - securing the API servers, etcd, nodes, container images, container run-time, and the cluster network. Apply principles of defense in depth, principle of least privilege, and minimize the attack surface. Use security tools such as [Kube-Bench](https://github.com/aquasecurity/kube-bench) to verify the cluster's security posture. Since Kubernetes is evolving rapidly refer to [Kubernetes Security Overview](https://kubernetes.io/docs/concepts/security/overview/) for the latest information on securing a Kubernetes cluster. Also ensure the deployed Docker containers follow the [Docker Security](https://docs.docker.com/engine/security/security/) guidance. + +This section provides references on how to securely configure Docker and Kubernetes. + +#### References + +1. Docker hardening + * https://docs.docker.com/engine/security/security/ + * https://blog.aquasec.com/docker-security-best-practices + +1. Kubernetes hardening + * https://kubernetes.io/docs/concepts/security/overview/ + * https://kubernetes.io/docs/concepts/security/pod-security-standards/ + * https://blogs.oracle.com/developers/5-best-practices-for-kubernetes-security + +1. Security best practices for Oracle WebLogic Server Running in Docker and Kubernetes + * https://blogs.oracle.com/weblogicserver/security-best-practices-for-weblogic-server-running-in-docker-and-kubernetes diff --git a/docs-source/content/wcportal-domains/appendix/quickstart-deployment-on-prem.md b/docs-source/content/wcportal-domains/appendix/quickstart-deployment-on-prem.md new file mode 100644 index 000000000..287a74f3a --- /dev/null +++ b/docs-source/content/wcportal-domains/appendix/quickstart-deployment-on-prem.md @@ -0,0 +1,750 @@ +--- +title: "Quick start deployment on-premise" +date: 2020-06-18T15:27:38-05:00 +weight: 2 +pre: " " +Description: "Describes how to quickly get an Oracle WebCenter Portal domain instance running (using the defaults, nothing special) for development and test purposes." +--- + +Use this Quick Start to create an Oracle WebCenter Portal domain deployment in a Kubernetes cluster (on-premise environments) with the WebLogic Kubernetes Operator. Note that this walkthrough is for demonstration purposes only, not for use in production. +These instructions assume that you are already familiar with Kubernetes. If you need more detailed instructions, +refer to the [Install Guide]({{< relref "/wcportal-domains/installguide/_index.md" >}}). + + +#### Hardware requirements + +The Linux kernel supported for deploying and running Oracle WebCenter Portal domains with the operator is Oracle Linux 7 (UL6+) and Red Hat Enterprise Linux 7 (UL3+ only with standalone Kubernetes). Refer to the [prerequisites]({{< relref "/wcportal-domains/installguide/prerequisites/_index.md" >}}) for more details. + +For this exercise, the minimum hardware requirements to create a single-node Kubernetes cluster and then deploy the domain type with one Managed Server along with Oracle Database running as a container are: + + Hardware|Size + --|-- + RAM|32GB + Disk Space|250GB+ + CPU core(s)|6 + +See [here]({{< relref "/wcportal-domains/appendix/wcp-cluster-sizing-info.md" >}}) for resource sizing information for Oracle WebCenter Portal domain set up on a Kubernetes cluster. + +### Set up Oracle WebCenter Portal in an on-premise environment +Use the steps in this topic to create a single-instance on-premise Kubernetes cluster and then create an Oracle WebCenter Portal domain. +* [Step 1 - Prepare a virtual machine for the Kubernetes cluster](#1-prepare-a-virtual-machine-for-the-kubernetes-cluster) +* [Step 2 - Set up a single instance Kubernetes cluster](#2-set-up-a-single-instance-kubernetes-cluster) +* [Step 3 - Get scripts and images](#3-get-scripts-and-images) +* [Step 4 - Install the WebLogic Kubernetes operator](#4-install-the-weblogic-kubernetes-operator) +* [Step 5 - Install the Traefik (ingress-based) load balancer](#5-install-the-traefik-ingress-based-load-balancer) +* [Step 6 - Create and configure an Oracle WebCenter Portal domain](#6-create-and-configure-an-oracle-webcenter-portal-domain) + + +### 1. Prepare a virtual machine for the Kubernetes cluster + +For illustration purposes, these instructions are for Oracle Linux 7u6+. If you are using a different flavor of Linux, you will need to adjust the steps accordingly. + +{{% notice note %}} These steps must be run with the `root` user, unless specified otherwise. +Any time you see `YOUR_USERID` in a command, you should replace it with your actual `userid`. +{{% /notice %}} + +#### 1.1 Prerequisites + +1. Choose the directories where your Docker and Kubernetes files will be stored. The Docker directory should be on a disk with a lot of free space (more than 100GB) because it will be used for the Docker file system, which contains all of your images and containers. The Kubernetes directory is used for the `/var/lib/kubelet` file system and persistent volume storage. + + ``` + $ export docker_dir=/u01/docker + $ export kubelet_dir=/u01/kubelet + $ mkdir -p $docker_dir $kubelet_dir + $ ln -s $kubelet_dir /var/lib/kubelet + ``` + +1. Verify that IPv4 forwarding is enabled on your host. + + **Note**: Replace eth0 with the ethernet interface name of your compute resource if it is different. + ``` + $ /sbin/sysctl -a 2>&1|grep -s 'net.ipv4.conf.docker0.forwarding' + $ /sbin/sysctl -a 2>&1|grep -s 'net.ipv4.conf.eth0.forwarding' + $ /sbin/sysctl -a 2>&1|grep -s 'net.ipv4.conf.lo.forwarding' + $ /sbin/sysctl -a 2>&1|grep -s 'net.ipv4.ip_nonlocal_bind' + ``` + + For example: Verify that all are set to 1: + ``` + $ net.ipv4.conf.docker0.forwarding = 1 + $ net.ipv4.conf.eth0.forwarding = 1 + $ net.ipv4.conf.lo.forwarding = 1 + $ net.ipv4.ip_nonlocal_bind = 1 + ``` + Solution: Set all values to 1 immediately: + ``` + $ /sbin/sysctl net.ipv4.conf.docker0.forwarding=1 + $ /sbin/sysctl net.ipv4.conf.eth0.forwarding=1 + $ /sbin/sysctl net.ipv4.conf.lo.forwarding=1 + $ /sbin/sysctl net.ipv4.ip_nonlocal_bind=1 + ``` + +1. **To preserve the settings permanently**: Update the above values to 1 in files in ``/usr/lib/sysctl.d/``, ``/run/sysctl.d/``, and ``/etc/sysctl.d/``. + +1. Verify the iptables rule for forwarding. + + Kubernetes uses iptables to handle many networking and port forwarding rules. A standard Docker installation may create a firewall rule that prevents forwarding. + + Verify if the iptables rule to accept forwarding traffic is set: + ``` + $ /sbin/iptables -L -n | awk '/Chain FORWARD / {print $4}' | tr -d ")" + ``` + + If the output is "DROP", then run the following command: + ``` + $ /sbin/iptables -P FORWARD ACCEPT + ``` + + Verify if the iptables rule is properly set to "ACCEPT": + ``` + $ /sbin/iptables -L -n | awk '/Chain FORWARD / {print $4}' | tr -d ")" + ``` + +1. Disable and stop `firewalld`: + + ``` + $ systemctl disable firewalld + $ systemctl stop firewalld + ``` + +#### 1.2 Install and configure Docker + +> Note: If you have already installed Docker with version 18.03+ and configured the Docker daemon root to sufficient disk space along with proxy settings, continue to [Install and configure Kubernetes](#13-install-and-configure-kubernetes). + +1. Make sure that you have the right operating system version: + ``` + $ uname -a + $ more /etc/oracle-release + ``` + Example output: + ``` + Linux xxxxxxx 4.1.12-124.27.1.el7uek.x86_64 #2 SMP Mon May 13 08:56:17 PDT 2019 x86_64 x86_64 x86_64 GNU/Linux + Oracle Linux Server release 7.6 + ``` + +1. Install the latest `docker-engine` and start the Docker service: + ``` + $ yum-config-manager --enable ol7_addons + $ docker_version="19.03.1.ol" + $ yum install docker-engine-$docker_version + + $ systemctl enable docker + $ systemctl start docker + ``` + +1. Add your user ID to the Docker group to allow you to run Docker commands without root access: + ``` + $ /sbin/usermod -a -G docker + ``` + +1. Check that your Docker version is at least 18.03: + ``` + $ docker version + ``` + Example output: + ``` + Client: Docker Engine - Community + Version: 19.03.1-ol + API version: 1.40 + Go version: go1.12.5 + Git commit: ead9442 + Built: Wed Sep 11 06:40:28 2019 + OS/Arch: linux/amd64 + Experimental: false + + Server: Docker Engine - Community + Engine: + Version: 19.03.1-ol + API version: 1.40 (minimum version 1.12) + Go version: go1.12.5 + Git commit: ead9442 + Built: Wed Sep 11 06:38:43 2019 + OS/Arch: linux/amd64 + Experimental: false + Default Registry: docker.io + containerd: + Version: v1.2.0-rc.0-108-gc444666 + GitCommit: c4446665cb9c30056f4998ed953e6d4ff22c7c39 + runc: + Version: 1.0.0-rc5+dev + GitCommit: 4bb1fe4ace1a32d3676bb98f5d3b6a4e32bf6c58 + docker-init: + Version: 0.18.0 + GitCommit: fec3683 + ``` + +1. Update the Docker engine configuration: + ``` + $ mkdir -p /etc/docker + + $ cat < /etc/docker/daemon.json + { + "group": "docker", + "data-root": "/u01/docker" + } + EOF + ``` + +1. Configure proxy settings if you are behind an HTTP proxy: + + ``` + ### Create the drop-in file /etc/systemd/system/docker.service.d/http-proxy.conf that contains proxy details: + $ cat < /etc/systemd/system/docker.service.d/http-proxy.conf + [Service] + Environment="HTTP_PROXY=http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT" + Environment="HTTPS_PROXY=http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT" + Environment="NO_PROXY=localhost,127.0.0.0/8,ADD-YOUR-INTERNAL-NO-PROXY-LIST,/var/run/docker.sock" + EOF + ``` + >Note: On some hosts `/etc/systemd/system/docker.service.d` may not be available. Create this directory if it is not available. + +1. Restart the Docker daemon to load the latest changes: + ``` + $ systemctl daemon-reload + $ systemctl restart docker + ``` + +1. Verify that the proxy is configured with Docker: + ``` + $ docker info|grep -i proxy + ``` + Example output: + ``` + HTTP Proxy: http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT + HTTPS Proxy: http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT + No Proxy: localhost,127.0.0.0/8,ADD-YOUR-INTERNAL-NO-PROXY-LIST,/var/run/docker.sock + ``` + +1. Verify Docker installation: + ``` + $ docker run hello-world + ``` + Example output: + ``` + Hello from Docker! + This message shows that your installation appears to be working correctly. + To generate this message, Docker took the following steps: + 1. The Docker client contacted the Docker daemon. + 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. + (amd64) + 3. The Docker daemon created a new container from that image which runs the + executable that produces the output you are currently reading. + 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. + To try something more ambitious, you can run an Ubuntu container with: + $ docker run -it ubuntu bash + Share images, automate workflows, and more with a free Docker ID: + https://hub.docker.com/ + For more examples and ideas, visit: + https://docs.docker.com/get-started/ + ``` + +#### 1.3 Install and configure Kubernetes + +1. Add the external Kubernetes repository: + ``` + $ cat < /etc/sysctl.d/k8s.conf + net.bridge.bridge-nf-call-ip6tables = 1 + net.bridge.bridge-nf-call-iptables = 1 + EOF + $ sysctl --system + ``` + +1. Disable swap check: + ``` + $ sed -i 's/KUBELET_EXTRA_ARGS=/KUBELET_EXTRA_ARGS="--fail-swap-on=false"/' /etc/sysconfig/kubelet + $ cat /etc/sysconfig/kubelet + ### Reload and restart kubelet + $ systemctl daemon-reload + $ systemctl restart kubelet + ``` + +#### 1.4 Set up Helm + +1. Install Helm v3.x. + + a. Download Helm from https://github.com/helm/helm/releases. + + For example, to download Helm v3.1.3: + ``` + $ wget https://get.helm.sh/helm-v3.1.3-linux-amd64.tar.gz + ``` + b. Unpack `tar.gz`: + ``` + $ tar -zxvf helm-v3.1.3-linux-amd64.tar.gz + ``` + c. Find the Helm binary in the unpacked directory, and move it to its desired destination: + ``` + $ mv linux-amd64/helm /usr/bin/helm + ``` + +1. Run `helm version` to verify its installation: + ``` + $ helm version + version.BuildInfo{Version:"v3.1.3", GitCommit:"0ad800ef43d3b826f31a5ad8dfbb4fe05d143688", GitTreeState:"clean", GoVersion:"go1.13.12"} + ``` + +### 2. Set up a single instance Kubernetes cluster + +> **Notes:** +> * These steps must be run with the `root` user, unless specified otherwise! +> * If you choose to use a different CIDR block (that is, other than `10.244.0.0/16` for the `--pod-network-cidr=` in the `kubeadm init` command), then also update `NO_PROXY` and `no_proxy` with the appropriate value. +> * Also make sure to update `kube-flannel.yaml` with the new value before deploying. +> * Replace the following with appropriate values: +> * `ADD-YOUR-INTERNAL-NO-PROXY-LIST` +> * `REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT` + +#### 2.1 Set up the master node +1. Create a shell script that sets up the necessary environment variables. You can append this to the user’s `.bashrc` so that it will run at login. You must also configure your proxy settings here if you are behind an HTTP proxy: + + ``` + ## grab my IP address to pass into kubeadm init, and to add to no_proxy vars + ip_addr=`nslookup $(hostname -f) | grep -m2 Address | tail -n1| awk -F: '{print $2}'| tr -d " "` + export pod_network_cidr="10.244.0.0/16" + export service_cidr="10.96.0.0/12" + export PATH=$PATH:/sbin:/usr/sbin + + ### Set the proxies + export NO_PROXY=localhost,127.0.0.0/8,ADD-YOUR-INTERNAL-NO-PROXY-LIST,/var/run/docker.sock,$ip_addr,$pod_network_cidr,$service_cidr + export no_proxy=localhost,127.0.0.0/8,ADD-YOUR-INTERNAL-NO-PROXY-LIST,/var/run/docker.sock,$ip_addr,$pod_network_cidr,$service_cidr + export http_proxy=http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT + export https_proxy=http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT + export HTTPS_PROXY=http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT + export HTTP_PROXY=http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT + ``` + +1. Source the script to set up your environment variables: + ``` + $ . ~/.bashrc + ``` + +1. To implement command completion, add the following to the script: + ``` + $ [ -f /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion + $ source <(kubectl completion bash) + ``` +1. Run `kubeadm init` to create the master node: + ``` + $ kubeadm init \ + --pod-network-cidr=$pod_network_cidr \ + --apiserver-advertise-address=$ip_addr \ + --ignore-preflight-errors=Swap > /tmp/kubeadm-init.out 2>&1 + ``` + +1. Log in to the terminal with `YOUR_USERID:YOUR_GROUP`. Then set up the `~/.bashrc` similar to steps 1 to 3 with `YOUR_USERID:YOUR_GROUP`. + + > Note that from now on we will be using `YOUR_USERID:YOUR_GROUP` to execute any `kubectl` commands and not `root`. + +1. Set up `YOUR_USERID:YOUR_GROUP` to access the Kubernetes cluster: + ``` + $ mkdir -p $HOME/.kube + $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config + $ sudo chown $(id -u):$(id -g) $HOME/.kube/config + ``` +1. Verify that `YOUR_USERID:YOUR_GROUP` is set up to access the Kubernetes cluster using the `kubectl` command: + + ``` + $ kubectl get nodes + ``` + > Note: At this step, the node is not in ready state as we have not yet installed the pod network add-on. After the next step, the node will show status as Ready. + +1. Install a pod network add-on (`flannel`) so that your pods can communicate with each other. + + > Note: If you are using a different CIDR block than `10.244.0.0/16`, then download and update `kube-flannel.yml` with the correct CIDR address before deploying into the cluster: + ``` + $ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.12.0/Documentation/kube-flannel.yml + ``` + +1. Verify that the master node is in Ready status: + ``` + $ kubectl get nodes + ``` + Sample output: + ``` + NAME STATUS ROLES AGE VERSION + mymasternode Ready master 8m26s v1.18.4 + ``` + or: + ``` + $ kubectl get pods -n kube-system + ``` + Sample output: + ``` + NAME READY STATUS RESTARTS AGE + pod/coredns-86c58d9df4-58p9f 1/1 Running 0 3m59s + pod/coredns-86c58d9df4-mzrr5 1/1 Running 0 3m59s + pod/etcd-mymasternode 1/1 Running 0 3m4s + pod/kube-apiserver-node 1/1 Running 0 3m21s + pod/kube-controller-manager-mymasternode 1/1 Running 0 3m25s + pod/kube-flannel-ds-amd64-6npx4 1/1 Running 0 49s + pod/kube-proxy-4vsgm 1/1 Running 0 3m59s + pod/kube-scheduler-mymasternode 1/1 Running 0 2m58s + ``` + +1. To schedule pods on the master node, `taint` the node: + ``` + $ kubectl taint nodes --all node-role.kubernetes.io/master- + ``` + +Congratulations! Your Kubernetes cluster environment is ready to deploy your Oracle WebCenter Portal domain. + +For additional references on Kubernetes cluster setup, check the [cheat sheet](https://oracle.github.io/weblogic-kubernetes-operator/userguide/overview/k8s-setup/). + +### 3. Get scripts and images + +#### 3.1 Set up the code repository to deploy Oracle WebCenter Portal + +Follow [these steps]({{< relref "/wcportal-domains/installguide/prepare-your-environment/#set-up-the-code-repository-to-deploy-oracle-webcenter-portal-domain" >}}) to set up the source code repository required to deploy Oracle WebCenter Portal domain. + +#### 3.2 Get required Docker images and add them to your local registry + +1. Pull the operator image: + + ``` + $ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.1.1 + ``` + +1. Obtain the Oracle Database image from the [Oracle Container Registry](https://container-registry.oracle.com): + + a. For first time users, to pull an image from the Oracle Container Registry, navigate to https://container-registry.oracle.com and log in using the Oracle Single Sign-On (SSO) authentication service. If you do not already have SSO credentials, you can create an Oracle Account using: + https://profile.oracle.com/myprofile/account/create-account.jspx. + + Use the web interface to accept the Oracle Standard Terms and Restrictions for the Oracle software images that you intend to deploy. Your acceptance of these terms are stored in a database that links the software images to your Oracle Single Sign-On login credentials. + + To obtain the image, log in to the Oracle Container Registry: + ``` + $ docker login container-registry.oracle.com + ``` + + b. Find and then pull the Oracle Database image for 12.2.0.1: + ``` + $ docker pull container-registry.oracle.com/database/enterprise:12.2.0.1-slim + ``` + + c. Build Oracle WebCenter Portal 12.2.1.4 Image by following steps from this [document]({{< relref "/wcportal-domains/create-or-update-image/">}}). + + +### 4. Install the WebLogic Kubernetes operator + +#### 4.1 Prepare for the WebLogic Kubernetes operator. +1. Create a namespace `operator-ns` for the operator: + ``` + $ kubectl create namespace operator-ns + ``` + +1. Create a service account `operator-sa` for the operator in the operator’s namespace: + ``` + $ kubectl create serviceaccount -n operator-ns operator-sa + ``` + +#### 4.2 Install the WebLogic Kubernetes operator + +Use Helm to install and start the operator from the directory you just cloned: + +``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm install weblogic-kubernetes-operator kubernetes/charts/weblogic-operator \ + --namespace operator-ns \ + --set image=oracle/weblogic-kubernetes-operator:3.1.1 \ + --set serviceAccount=operator-sa \ + --set "domainNamespaces={}" \ + --wait +``` +#### 4.3 Verify the WebLogic Kubernetes operator + +1. Verify that the operator’s pod is running by listing the pods in the operator’s namespace. You should see one for the operator: + ``` + $ kubectl get pods -n operator-ns + ``` + +1. Verify that the operator is up and running by viewing the operator pod's logs: + ``` + $ kubectl logs -n operator-ns -c weblogic-operator deployments/weblogic-operator + ``` + +The WebLogic Kubernetes operator v3.1.1 has been installed. Continue with the load balancer and Oracle WebCenter Portal domain setup. + +### 5. Install the Traefik (ingress-based) load balancer + +The WebLogic Kubernetes Operator supports three load balancers: Traefik, Voyager, and Apache. Samples are provided in the documentation. + +This Quick Start demonstrates how to install the Traefik ingress controller to provide load balancing for an Oracle WebCenter Portal domain. + +1. Create a namespace for Traefik: + ``` + $ kubectl create namespace traefik + ``` + +1. Set up Helm for 3rd party services: + ``` + $ helm repo add traefik https://containous.github.io/traefik-helm-chart + ``` + +1. Install the Traefik operator in the `traefik` namespace with the provided sample values: + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm install traefik traefik/traefik \ + --namespace traefik \ + --values kubernetes/samples/scripts/charts/traefik/values.yaml \ + --set "kubernetes.namespaces={traefik}" \ + --set "service.type=NodePort" \ + --wait + ``` + +### 6. Create and configure an Oracle WebCenter Portal domain +#### 6.1 Prepare for an Oracle WebCenter Portal domain + +1. Create a namespace that can host Oracle WebCenter Portal domain: + ``` + $ kubectl create namespace wcpns + ``` + +1. Use Helm to configure the operator to manage Oracle WebCenter Portal domain in this namespace: + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm upgrade weblogic-kubernetes-operator kubernetes/charts/weblogic-operator \ + --reuse-values \ + --namespace operator-ns \ + --set "domainNamespaces={wcpns}" \ + --wait + ``` + +1. Create Kubernetes secrets. + + a. Create a Kubernetes secret for the domain in the same Kubernetes namespace as the domain. In this example, the username is `weblogic`, the password is `welcome1`, and the namespace is `wcpns`: + + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-weblogic-domain-credentials + $ sh create-weblogic-credentials.sh -u weblogic -p welcome1 -n wcpns -d wcp-domain -s wcpinfra-domain-credentials + ``` + + b. Create a Kubernetes secret for the RCU in the same Kubernetes namespace as the domain: + + * Schema user : `WCP1` + * Schema password : `Oradoc_db1` + * DB sys user password : `Oradoc_db1` + * Domain name : `wcp-domain` + * Domain Namespace : `wcpns` + * Secret name : `wcpinfra-rcu-credentials` + + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-rcu-credentials + $ sh create-rcu-credentials.sh -u WCP1 -p Oradoc_db1 -a sys -q Oradoc_db1 -n wcpns -d wcp-domain -s wcpinfra-rcu-credentials + ``` + +1. Create the Kubernetes persistence volume and persistence volume claim. + + a. Create the Oracle WebCenter Portal domain home directory. + Determine if a user already exists on your host system with `uid:gid` of `1000`: + ``` + $ sudo getent passwd 1000 + ``` + + If this command returns a username (which is the first field), you can skip the following `useradd` command. If not, create the oracle user with `useradd`: + ``` + $ sudo useradd -u 1000 -g 1000 oracle + ``` + + Create the directory that will be used for the Oracle WebCenter Portal domain home: + ``` + $ sudo mkdir /scratch/k8s_dir + $ sudo chown -R 1000:1000 /scratch/k8s_dir + ``` + + b. Update `create-pv-pvc-inputs.yaml` with the following values: + + * baseName: `domain` + * domainUID: `wcp-domain` + * namespace: `wcpns` + * weblogicDomainStoragePath: `/scratch/k8s_dir` + + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-weblogic-domain-pv-pvc + $ cp create-pv-pvc-inputs.yaml create-pv-pvc-inputs.yaml.orig + $ sed -i -e "s:baseName\: weblogic-sample:baseName\: domain:g" create-pv-pvc-inputs.yaml + $ sed -i -e "s:domainUID\::domainUID\: wcp-domain:g" create-pv-pvc-inputs.yaml + $ sed -i -e "s:namespace\: default:namespace\: wcpns:g" create-pv-pvc-inputs.yaml + $ sed -i -e "s:#weblogicDomainStoragePath\: /scratch/k8s_dir:weblogicDomainStoragePath\: /scratch/k8s_dir:g" create-pv-pvc-inputs.yaml + ``` + + c. Run the `create-pv-pvc.sh` script to create the PV and PVC configuration files: + ``` + $ ./create-pv-pvc.sh -i create-pv-pvc-inputs.yaml -o output + ``` + + d. Create the PV and PVC using the configuration files created in the previous step: + ``` + $ kubectl create -f output/pv-pvcs/wcp-domain-domain-pv.yaml + $ kubectl create -f output/pv-pvcs/wcp-domain-domain-pvc.yaml + ``` + +1. Install and configure the database for the Oracle WebCenter Portal domain. + + This step is required only when a standalone database is not already set up and you want to use the database in a container. + + {{% notice warning %}} + The Oracle Database Docker images are supported only for non-production use. For more details, see My Oracle Support note: Oracle Support for Database Running on Docker (Doc ID 2216342.1). For production, it is suggested to use a standalone database. This example provides steps to create the database in a container. + {{% /notice %}} + + a. Create a database in a container: + + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-oracle-db-service + $ ./start-db-service.sh -i container-registry.oracle.com/database/enterprise:12.2.0.1-slim -p none + ``` + + Once the database is successfully created, you can use the database connection string `oracle-db.default.svc.cluster.local:1521/devpdb.k8s` as an `rcuDatabaseURL` parameter in the `create-domain-inputs.yaml` file. + + b. Create Oracle WebCenter Portal schemas. + + To create the Oracle WebCenter Portal schemas, run the following commands: + ``` + $ kubectl run rcu --generator=run-pod/v1 --image oracle/wcportal:12.2.1.4 -n wcpns -- sleep infinity + #check the status of rcu pod + $ kubectl get pods -n wcpns + #make sure rcu pod status is running before executing this + $ kubectl exec -n wcpns -ti rcu /bin/bash + #After Getting Shell in RCU Container run the below command. + export CONNECTION_STRING=oracle-db.default.svc.cluster.local:1521/devpdb.k8s + export RCUPREFIX=WCP1 + echo -e Oradoc_db1"\n"Oradoc_db1 > /tmp/pwd.txt + /u01/oracle/oracle_common/bin/rcu -silent -dropRepository -databaseType ORACLE -connectString $CONNECTION_STRING -dbUser sys -dbRole sysdba -selectDependentsForComponents true -schemaPrefix $RCUPREFIX -component OPSS -component IAU_VIEWER -component WEBCENTER -component MDS -component IAU_APPEND -component STB -component IAU -component WLS -f < /tmp/pwd.txt + /u01/oracle/oracle_common/bin/rcu -silent -createRepository -databaseType ORACLE -connectString $CONNECTION_STRING -dbUser sys -dbRole sysdba -useSamePasswordForAllSchemaUsers true -selectDependentsForComponents true -schemaPrefix $RCUPREFIX -component OPSS -component IAU_VIEWER -component WEBCENTER -component MDS -component IAU_APPEND -component STB -component IAU -component WLS -tablespace USERS -tempTablespace TEMP -f < /tmp/pwd.txt + #exit from the container + exit + + ``` + +Now the environment is ready to start the Oracle WebCenter Portal domain creation. + + +#### 6.2 Create an Oracle WebCenter Portal domain + +1. The sample scripts for Oracle WebCenter Portal domain deployment are available at `/kubernetes/samples/scripts/create-wcp-domain`. You must edit `create-domain-inputs.yaml` (or a copy of it) to provide the details for your domain. + + Update `create-domain-inputs.yaml` with the following values for domain creation: + + * `rcuDatabaseURL`: `oracle-db.default.svc.cluster.local:1521/devpdb.k8s` + + +1. Run the `create-domain.sh` script to create a domain: + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv/ + $ ./create-domain.sh -i create-domain-inputs.yaml -o output + ``` + +1. Create a Kubernetes domain object: + + Once the `create-domain.sh` is successful, it generates `output/weblogic-domains/wcp-domain/domain.yaml`, which you can use to create the Kubernetes resource domain to start the domain and servers: + + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv + $ kubectl create -f output/weblogic-domains/wcp-domain/domain.yaml + ``` + +1. Verify that the Kubernetes domain object named `wcp-domain` is created: + ``` + $ kubectl get domain -n wcpns + NAME AGE + wcp-domain 3m18s + ``` + +1. Once you create the domain, the *introspect pod* is created. This inspects the domain home and then starts the `wcp-domain-adminserver` pod. Once the `wcp-domain-adminserver` pod starts successfully, the Managed Server pods are started in parallel. +Watch the `wcpns` namespace for the status of domain creation: + ``` + $ kubectl get pods -n wcpns -w + ``` + +1. Verify that the Oracle WebCenter Portal domain server pods and services are created and in Ready state: + ``` + $ kubectl get all -n wcpns + ``` + +#### 6.3 Configure Traefik to access Oracle WebCenter Portal domain services + +1. Configure Traefik to manage ingresses created in the Oracle WebCenter Portal domain namespace (`wcpns`): + ``` + $ helm upgrade traefik traefik/traefik \ + --reuse-values \ + --namespace traefik \ + --set "kubernetes.namespaces={traefik,wcpns}" \ + --wait + ``` + +1. Create an ingress for the domain in the domain namespace by using the sample Helm chart: + ``` + $ cd ${WORKDIR}/weblogic-kubernetes-operator + helm install wcp-traefik-ingress \ + kubernetes/samples/charts/ingress-per-domain \ + --namespace wcpns \ + --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --set "traefik.hostname=$(hostname -f)" + ``` +1. Verify the created ingress per domain details: + ``` + $ kubectl describe ingress wcp-domain-traefik -n wcpns + ``` + +#### 6.4 Verify that you can access the Oracle WebCenter Portal domain URL + +1. Get the `LOADBALANCER_HOSTNAME` for your environment: + ``` + export LOADBALANCER_HOSTNAME=$(hostname -f) + ``` +1. Verify the following URLs are available for Oracle WebCenter Portal domain. + + Credentials: + + *username*: `weblogic` + *password*: `welcome1` + + ``` + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenter + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/console + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/em + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rsscrawl + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rest + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenterhelp + ``` diff --git a/docs-source/content/wcportal-domains/appendix/wcp-cluster-sizing-info.md b/docs-source/content/wcportal-domains/appendix/wcp-cluster-sizing-info.md new file mode 100644 index 000000000..35f1307e4 --- /dev/null +++ b/docs-source/content/wcportal-domains/appendix/wcp-cluster-sizing-info.md @@ -0,0 +1,18 @@ +--- +title: "Domain resource sizing" +date: 2019-02-22T15:44:42-05:00 +draft: false +weight: 1 +pre : " " +description: "Describes the resourse sizing information for the Oracle WebCenter Portal domain setup on Kubernetes cluster." +--- + +### Oracle WebCenter Portal cluster sizing recommendations + +WebCenter Portal | Normal Usage | Moderate Usage | High Usage +--- | --- | --- | --- +Admin Server | No of CPU(s) : 1, Memory : 4GB | No of CPU(s) : 1, Memory : 4GB | No of CPU(s) : 1, Memory : 4GB +Number of Managed Server | No of Servers : 2 | No of Servers : 2 | No of Servers : 3 +Configurations per Managed Server | No of CPU(s) : 2, Memory : 16GB | No of CPU(s) : 4, Memory : 16GB | No of CPU(s) : 6, Memory : 16-32GB +PV Storage | Minimum 250GB | Minimum 250GB | Minimum 500GB + diff --git a/docs-source/content/wcportal-domains/cleanup-domain-setup.md b/docs-source/content/wcportal-domains/cleanup-domain-setup.md new file mode 100644 index 000000000..efbcf1b75 --- /dev/null +++ b/docs-source/content/wcportal-domains/cleanup-domain-setup.md @@ -0,0 +1,38 @@ +--- +title: "Uninstall an Oracle WebCenter Portal domain" +date: 2019-02-22T15:44:42-05:00 +draft: false +weight: 5 +pre : "5. " +description: "Clean up the Oracle WebCenter Portal domain setup." +--- + +To clean up the Oracle WebCenter Portal domain setup, follow the steps below. + +#### Delete the Generated Domain Home + +To remove a domain home that you generated by running the `create-domain.sh` script in your production or testing environment, use the `delete-domain-job.yaml` file located at, `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv/output/weblogic-domains/wcp-domain>` directory. + +``` +$ kubectl create -f delete-domain-job.yaml +``` + +#### Clean Up the create-domain-job script After Execution Failure +To clean up the `create-domain-job` script: + +1. Get the create domain job and configmaps: + + ```bash + $ kubectl get configmaps,jobs -n wcpns |grep "create-domain-job" + ``` +2. Delete the job and configmap: + + ```bash + $ kubectl delete job job.batch/wcp-domain-create-fmw-infra-sample-domain-job -n wcpns + $ kubectl delete configmap wcp-domain-create-fmw-infra-sample-domain-job-cm -n wcpns + ``` +3. Delete the contents of the PV, if any: + + ```bash + $ sudo rm -rf /scratch/kubevolume + diff --git a/docs-source/content/wcportal-domains/create-or-update-image/_index.md b/docs-source/content/wcportal-domains/create-or-update-image/_index.md new file mode 100644 index 000000000..5515d5115 --- /dev/null +++ b/docs-source/content/wcportal-domains/create-or-update-image/_index.md @@ -0,0 +1,1173 @@ ++++ +title= "Create or update an image" +date = 2019-04-18T06:46:23-05:00 +weight = 4 +pre = "4. " +description = "Create or update an Oracle WebCenter Portal Docker image used for deploying Oracle WebCenter Portal domains. An Oracle WebCenter Portal Docker image can be created using the WebLogic Image Tool or using the Dockerfile approach." ++++ + +You can build an Oracle WebCenter Portal image for production deployments with patches (bundle or interim) using the WebLogic Image Tool, you must have access to the My Oracle Support (MOS) to download (bundle or interim) patches. + +* [Create or update an Oracle WebCenter Portal Docker image using the WebLogic Image Tool](#create-or-update-an-oracle-webcenter-portal-docker-image-using-the-weblogic-image-tool) + * [Set up the WebLogic Image Tool](#set-up-the-weblogic-image-tool) + * [Create an image](#create-an-image) + * [Update an image](#update-an-image) +* [Create an Oracle WebCenter Portal Docker image using Dockerfile](#create-an-oracle-webcenter-portal-docker-image-using-dockerfile) + + +### Create or update an Oracle WebCenter Portal Docker image using the WebLogic Image Tool + +Using the WebLogic Image Tool, you can [create]({{< relref "/wcportal-domains/create-or-update-image/#create-an-image" >}}) a new Oracle WebCenter Portal Docker image (can include patches as well) or [update]({{< relref "/wcportal-domains/create-or-update-image/#update-an-image" >}}) an existing image with one or more patches (bundle patch and interim patches). + +> **Recommendations:** +> * Use [create]({{< relref "/wcportal-domains/create-or-update-image/#create-an-image" >}}) for creating a new Oracle WebCenter Portal Docker image: +> * without any patches +> * or, containing the Oracle WebCenter Portal binaries, bundle , and interim patches. This is the recommended approach if you have access to the Oracle WebCenter Portal patches because it optimizes the size of the image. +> * Use [update]({{< relref "/wcportal-domains/create-or-update-image/#update-an-image" >}}) for patching an existing Oracle WebCenter Portal Docker image with a single interim patch. Note that the patched image size may increase considerably due to additional image layers introduced by the patch application tool. + + + +* [Prerequisites](#prerequisites) +* [Set up the WebLogic Image Tool](#set-up-the-weblogic-image-tool) +* [Validate the setup](#validate-the-setup) +* [WebLogic Image Tool build directory](#weblogic-image-tool-build-directory) +* [WebLogic Image Tool cache](#weblogic-image-tool-cache) +* [Set up additional build scripts](#set-up-additional-build-scripts) + +##### Prerequisites + +Verify that your environment meets the following prerequisites: + +* Docker client and daemon on the build machine, with minimum Docker version 18.03.1.ce. +* Bash version 4.0 or later, to enable the command complete feature. +* JAVA_HOME environment variable set to the appropriate JDK location. + +##### Set up the WebLogic Image Tool + +To set up the WebLogic Image Tool: + +1. Create a working directory and change to it. In these steps, this directory is `imagetool-setup`. + ```bash + $ mkdir imagetool-setup + $ cd imagetool-setup + ``` +1. Download the latest version of the WebLogic Image Tool from the [releases page](https://github.com/oracle/weblogic-image-tool/releases/latest). +1. Unzip the release ZIP file to the `imagetool-setup` directory. +1. Execute the following commands to set up the WebLogic Image Tool on a Linux environment: + + ```bash + $ cd imagetool-setup/imagetool/bin + $ source setup.sh + ``` + +##### Validate the setup +To validate the setup of the WebLogic Image Tool: + +1. Enter the following command to retrieve the version of the WebLogic Image Tool: + + ``` bash + $ imagetool --version + ``` + +2. Enter `imagetool` then press the Tab key to display the available `imagetool` commands: + + ``` bash + $ imagetool + cache create help rebase update + ``` + +##### WebLogic Image Tool build directory + +The WebLogic Image Tool creates a temporary Docker context directory, prefixed by `wlsimgbuilder_temp`, every time the tool runs. Under normal circumstances, this context directory is deleted. However, if the process is aborted or the tool is unable to remove the directory, it is safe for you to delete it manually. By default, the WebLogic Image Tool creates the Docker context directory under the user's home directory. If you prefer to use a different directory for the temporary context, set the environment variable `WLSIMG_BLDDIR`: + +``` bash +$ export WLSIMG_BLDDIR="/path/to/buid/dir" +``` + +##### WebLogic Image Tool cache + +The WebLogic Image Tool maintains a local file cache store. This store is used to look up where the Java, WebLogic Server installers, and WebLogic Server patches reside in the local file system. By default, the cache store is located in the user's `$HOME/cache` directory. Under this directory, the lookup information is stored in the `.metadata` file. All automatically downloaded patches also reside in this directory. You can change the default cache store location by setting the environment variable `WLSIMG_CACHEDIR`: + +```bash +$ export WLSIMG_CACHEDIR="/path/to/cachedir" +``` + +##### Set up additional build scripts + +To create an Oracle WebCenter Portal Docker image using the WebLogic Image Tool, additional container scripts for Oracle WebCenter Portal domains are required. +1. Clone the [docker-images](https://github.com/oracle/docker-images.git) repository to set up those scripts. In these steps, this directory is `DOCKER_REPO`: + + ```bash + $ cd imagetool-setup + $ git clone https://github.com/oracle/docker-images.git + ``` +1. Copy the additional WebLogic Image Tool build files from the operator source repository to the `imagetool-setup` location: + + ```bash + $ mkdir -p imagetool-setup/docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0 + $ cd imagetool-setup/docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0 + $ cp -rf ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/imagetool-scripts/* . + ``` +>Note: To create the image, continue with the following steps. To update the image, see [update an image](#update-an-image). + +#### Create an image +After [setting up the WebLogic Image Tool]({{< relref "/wcportal-domains/create-or-update-image/#set-up-the-weblogic-image-tool" >}}) and configuring the required build scripts, create a new Oracle WebCenter Portal Docker image using the WebLogic Image Tool as described ahead. + +##### Download the Oracle WebCenter Portal installation binaries and patches + +You must download the required Oracle WebCenter Portal installation binaries and patches listed below from the [Oracle Software Delivery Cloud](https://edelivery.oracle.com/) and save them in a directory of your choice. In these steps, the directory is `download location`. + +The installation binaries and patches required for release 21.2.1 are: + +* JDK: + * jdk-8u281-linux-x64.tar.gz + +* Fusion Middleware Infrastructure installer: + * fmw_12.2.1.4.0_infrastructure.jar + +* WCP installers: + * fmw_12.2.1.4.0_wcportal.jar + +* Fusion Middleware Infrastructure patches: + * p28186730_139425_Generic.zip (OPatch) + * p32253037_122140_Generic.zip(WLS) + * p31544353_122140_Linux-x86-64.zip(WLS ADR Patch) + * p32124456_122140_Generic.zip(Bundle patch for Oracle Coherence Version 12.2.1.4.7) + * p31666198_122140_Generic.zip(OPSS Bundle Patch 12.2.1.4.200724) + * p32357288_122140_Generic.zip(ADF BUNDLE PATCH 12.2.1.4.210107) + +* WCP patches: + * p32224021_122140_Generic.zip(WCP BUNDLE PATCH 12.2.1.4.201126) + * p31852495_122140_Generic.zip(WEBCENTER CORE BUNDLE PATCH 12.2.1.4.200905)) + +##### Update required build files + +The following files in the code repository location `/docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0` are used for creating the image: + +* `additionalBuildCmds.txt` +* `buildArgs` + +1. In the `buildArgs` file, update all occurrences of `%DOCKER_REPO%` with the `docker-images` repository location, which is the complete path of `/docker-images`. + + For example, update: + + `%DOCKER_REPO%/OracleWebCenterPortal/imagetool/12.2.1.4.0/` + + to: + + `/docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0/` + + +1. Similarly, update the placeholders `%JDK_VERSION%` and `%BUILDTAG%` with appropriate values. + +1. Update the response file `/docker-images/OracleFMWInfrastructure/dockerfiles/12.2.1.4/install.file` to add the parameter `INSTALL_TYPE="Fusion Middleware Infrastructure"` in the `[GENERIC]` section. + + +##### Create the image + +1. Add a JDK package to the WebLogic Image Tool cache: + + ``` bash + $ imagetool cache addInstaller --type jdk --version 8u281 --path /jdk-8u281-linux-x64.tar.gz + ``` + +1. Add the downloaded installation binaries to the WebLogic Image Tool cache: + + ``` bash + $ imagetool cache addInstaller --type fmw --version 12.2.1.4.0 --path /fmw_12.2.1.4.0_infrastructure.jar + + $ imagetool cache addInstaller --type wcp --version 12.2.1.4.0 --path /fmw_12.2.1.4.0_wcportal.jar + + ``` +1. Add the downloaded OPatch patch to the WebLogic Image Tool cache: + + ``` bash + $ imagetool cache addEntry --key 28186730_13.9.4.2.5 --value /p28186730_139425_Generic.zip + ``` + +1. Append the `--opatchBugNumber` flag and the OPatch patch key to the `create` command in the `buildArgs` file: + + ``` bash + --opatchBugNumber 28186730_13.9.4.2.5 + ``` + +1. Add the downloaded product patches to the WebLogic Image Tool cache: + + ``` bash + $ imagetool cache addEntry --key 32253037_12.2.1.4.0 --value /p32253037_122140_Generic.zip + + $ imagetool cache addEntry --key 32124456_12.2.1.4.0 --value /p32124456_122140_Generic.zip + + $ imagetool cache addEntry --key 32357288_12.2.1.4.0 --value /p32357288_122140_Generic.zip + + $ imagetool cache addEntry --key 32224021_12.2.1.4.0 --value /p32224021_122140_Generic.zip + + $ imagetool cache addEntry --key 31666198_12.2.1.4.0 --value /p31666198_122140_Generic.zip + + $ imagetool cache addEntry --key 31544353_12.2.1.4.0 --value /p31544353_122140_Linux-x86-64.zip + + $ imagetool cache addEntry --key 31852495_12.2.1.4.0 --value /p31852495_122140_Generic.zip + ``` + +1. Append the `--patches` flag and the product patch keys to the `create` command in the `buildArgs` file. The `--patches` list must be a comma-separated collection of patch `--key` values used in the `imagetool cache addEntry` commands above. + + Sample `--patches` list for the product patches added in to the cache: + + ``` + --patches 32253037_12.2.1.4.0,32124456_12.2.1.4.0,32357288_12.2.1.4.0,32224021_12.2.1.4.0 + ``` + + Example `buildArgs` file after appending the OPatch patch and product patches: + + ``` + create + --jdkVersion=8u281 + --type wcp + --version=12.2.1.4.0 + --tag=oracle/wcportal:12.2.1.4 + --pull + --additionalBuildCommands /docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0/additionalBuildCmds.txt + --additionalBuildFiles /docker-images/OracleWebCenterPortal/dockerfiles/12.2.1.4/container-scripts + --opatchBugNumber 28186730_13.9.4.2.5 + --patches 32253037_12.2.1.4.0,32124456_12.2.1.4.0,32357288_12.2.1.4.0,32224021_12.2.1.4.0,31666198_12.2.1.4.0,31544353_12.2.1.4.0,31852495_12.2.1.4.0 + ``` + >Note: In the `buildArgs` file: + > * `--jdkVersion` value must match the `--version` value used in the `imagetool cache addInstaller` command for `--type jdk`. + > * `--version` value must match the `--version` value used in the `imagetool cache addInstaller` command for `--type wcp`. + > * `--pull` always pulls the latest base Linux image `oraclelinux:7-slim` from the Docker registry. This flag can be removed if you want to use the Linux image `oraclelinux:7-slim`, which is already available on the host where the WCP image is created. + + Refer to [this page](https://github.com/oracle/weblogic-image-tool/blob/master/site/create-image.md) for the complete list of options available with the WebLogic Image Tool `create` command. + +1. Create the Oracle WebCenter Portal image: + + ```bash + $ imagetool @ + ``` + >Note: Make sure that the absolute path to the `buildargs` file is prepended with a `@` character, as shown in the example above. + + For example: + + ```bash + $ imagetool @/docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0/buildArgs + ``` + + {{%expand "Click here to see the sample Dockerfile generated with the imagetool command." %}} + ########## BEGIN DOCKERFILE ########## + # + # Copyright (c) 2019, 2021, Oracle and/or its affiliates. + # + # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + # + # + FROM ghcr.io/oracle/oraclelinux:7-slim as os_update + LABEL com.oracle.weblogic.imagetool.buildid="dabe3ff7-ec35-4b8d-b62a-c3c02fed5571" + USER root + + RUN yum -y --downloaddir=/tmp/imagetool install gzip tar unzip libaio jq hostname procps sudo zip \ + && yum -y --downloaddir=/tmp/imagetool clean all \ + && rm -rf /var/cache/yum/* \ + && rm -rf /tmp/imagetool + + ## Create user and group + RUN if [ -z "$(getent group oracle)" ]; then hash groupadd &> /dev/null && groupadd oracle || exit -1 ; fi \ + && if [ -z "$(getent passwd oracle)" ]; then hash useradd &> /dev/null && useradd -g oracle oracle || exit -1; fi \ + && mkdir -p /u01 \ + && chown oracle:oracle /u01 \ + && chmod 775 /u01 + + # Install Java + FROM os_update as jdk_build + LABEL com.oracle.weblogic.imagetool.buildid="dabe3ff7-ec35-4b8d-b62a-c3c02fed5571" + + ENV JAVA_HOME=/u01/jdk + + COPY --chown=oracle:oracle jdk-8u251-linux-x64.tar.gz /tmp/imagetool/ + + USER oracle + + + RUN tar xzf /tmp/imagetool/jdk-8u251-linux-x64.tar.gz -C /u01 \ + && $(test -d /u01/jdk* && mv /u01/jdk* /u01/jdk || mv /u01/graal* /u01/jdk) \ + && rm -rf /tmp/imagetool \ + && rm -f /u01/jdk/javafx-src.zip /u01/jdk/src.zip + + + # Install Middleware + FROM os_update as wls_build + LABEL com.oracle.weblogic.imagetool.buildid="dabe3ff7-ec35-4b8d-b62a-c3c02fed5571" + + ENV JAVA_HOME=/u01/jdk \ + ORACLE_HOME=/u01/oracle \ + OPATCH_NO_FUSER=true + + RUN mkdir -p /u01/oracle \ + && mkdir -p /u01/oracle/oraInventory \ + && chown oracle:oracle /u01/oracle/oraInventory \ + && chown oracle:oracle /u01/oracle + + COPY --from=jdk_build --chown=oracle:oracle /u01/jdk /u01/jdk/ + + COPY --chown=oracle:oracle fmw_12.2.1.4.0_infrastructure.jar fmw.rsp /tmp/imagetool/ + COPY --chown=oracle:oracle fmw_12.2.1.4.0_wcportal.jar wcp.rsp /tmp/imagetool/ + COPY --chown=oracle:oracle oraInst.loc /u01/oracle/ + + COPY --chown=oracle:oracle p28186730_139425_Generic.zip /tmp/imagetool/opatch/ + + COPY --chown=oracle:oracle patches/* /tmp/imagetool/patches/ + + USER oracle + + + RUN echo "INSTALLING MIDDLEWARE" \ + && echo "INSTALLING fmw" \ + && \ + /u01/jdk/bin/java -Xmx1024m -jar /tmp/imagetool/fmw_12.2.1.4.0_infrastructure.jar -silent ORACLE_HOME=/u01/oracle \ + -responseFile /tmp/imagetool/fmw.rsp -invPtrLoc /u01/oracle/oraInst.loc -ignoreSysPrereqs -force -novalidation \ + && echo "INSTALLING wcp" \ + && \ + /u01/jdk/bin/java -Xmx1024m -jar /tmp/imagetool/fmw_12.2.1.4.0_wcportal.jar -silent ORACLE_HOME=/u01/oracle \ + -responseFile /tmp/imagetool/wcp.rsp -invPtrLoc /u01/oracle/oraInst.loc -ignoreSysPrereqs -force -novalidation \ + && chmod -R g+r /u01/oracle + + RUN cd /tmp/imagetool/opatch \ + && /u01/jdk/bin/jar -xf /tmp/imagetool/opatch/p28186730_139425_Generic.zip \ + && /u01/jdk/bin/java -jar /tmp/imagetool/opatch/6880880/opatch_generic.jar -silent -ignoreSysPrereqs -force -novalidation oracle_home=/u01/oracle + + # Apply all patches provided at the same time + RUN /u01/oracle/OPatch/opatch napply -silent -oh /u01/oracle -phBaseDir /tmp/imagetool/patches \ + && test $? -eq 0 \ + && /u01/oracle/OPatch/opatch util cleanup -silent -oh /u01/oracle \ + || (cat /u01/oracle/cfgtoollogs/opatch/opatch*.log && exit 1) + + + + FROM os_update as final_build + + ARG ADMIN_NAME + ARG ADMIN_HOST + ARG ADMIN_PORT + ARG MANAGED_SERVER_PORT + + ENV ORACLE_HOME=/u01/oracle \ + JAVA_HOME=/u01/jdk \ + PATH=${PATH}:/u01/jdk/bin:/u01/oracle/oracle_common/common/bin:/u01/oracle/wlserver/common/bin:/u01/oracle + + LABEL com.oracle.weblogic.imagetool.buildid="dabe3ff7-ec35-4b8d-b62a-c3c02fed5571" + + COPY --from=jdk_build --chown=oracle:oracle /u01/jdk /u01/jdk/ + + COPY --from=wls_build --chown=oracle:oracle /u01/oracle /u01/oracle/ + + + + USER oracle + WORKDIR /u01/oracle + + #ENTRYPOINT /bin/bash + + + ENV ORACLE_HOME=/u01/oracle \ + SCRIPT_FILE=/u01/oracle/container-scripts/* \ + USER_MEM_ARGS="-Djava.security.egd=file:/dev/./urandom" \ + PATH=$PATH:/usr/java/default/bin:/u01/oracle/oracle_common/common/bin:/u01/oracle/wlserver/common/bin:/u01/oracle/container-scripts + + USER root + + RUN env && \ + mkdir -p /u01/oracle/container-scripts && \ + mkdir -p /u01/oracle/logs && \ + mkdir -p /u01/esHome/esNode && \ + chown oracle:oracle -R /u01 $VOLUME_DIR && \ + chmod a+xr /u01 + + COPY --chown=oracle:oracle files/container-scripts/ /u01/oracle/container-scripts/ + RUN chmod +xr $SCRIPT_FILE && \ + rm /u01/oracle/oracle_common/lib/ons.jar /u01/oracle/oracle_common/modules/oracle.jdbc/simplefan.jar + + USER oracle + EXPOSE $WCPORTAL_PORT $ADMIN_PORT + + WORKDIR ${ORACLE_HOME} + CMD ["/u01/oracle/container-scripts/configureOrStartAdminServer.sh"] + + + + ########## END DOCKERFILE ########## + + {{% /expand %}} + +1. Check the created image using the `docker images` command: + + ```bash + $ docker images | grep wcportal + ``` + +#### Update an image + +After [setting up the WebLogic Image Tool]({{< relref "/wcportal-domains/create-or-update-image/#set-up-the-weblogic-image-tool" >}}) and configuring the build scripts, use the WebLogic Image Tool to `update` an existing Oracle WebCenter Portal Docker image: + +1. Enter the following command to add the OPatch patch to the WebLogic Image Tool cache: + + ```bash + $ imagetool cache addEntry --key 28186730_13.9.4.2.5 --value /p28186730_139425_Generic.zip + ``` +1. Execute the `imagetool cache addEntry` command for each patch to add the required patch(es) to the WebLogic Image Tool cache. For example, to add patch `p30761841_122140_Generic.zip`: + + ```bash wrap + $ imagetool cache addEntry --key=32224021_12.2.1.4.0 --value /p32224021_122140_Generic.zip + ``` +1. Provide the following arguments to the WebLogic Image Tool `update` command: + + * `–-fromImage` - Identify the image that needs to be updated. In the example below, the image to be updated is `oracle/wcportal:12.2.1.4`. + * `–-patches` - Multiple patches can be specified as a comma-separated list. + * `--tag` - Specify the new tag to be applied for the image being built. + + Refer [here](https://github.com/oracle/weblogic-image-tool/blob/master/site/update-image.md) for the complete list of options available with the WebLogic Image Tool `update` command. + + > Note: The WebLogic Image Tool cache should have the latest OPatch zip. The WebLogic Image Tool updates the OPatch if it is not already updated in the image. + + ##### Examples + + {{%expand "Click here to see the example of update command:" %}} + + + $ imagetool update --fromImage oracle/wcportal:12.2.1.4 --tag=wcportal:12.2.1.4-32224021 --patches=32224021_12.2.1.4.0 + [INFO ] Image Tool build ID: 50f9b9aa-596c-4bae-bdff-c47c16b4c928 + [INFO ] Temporary directory used for docker build context: /scratch/asirasag/imagetoolcache/builddir/wlsimgbuilder_temp5130105621506307568 + [INFO ] Using patch 28186730_13.9.4.2.5 from cache: /home/asirasag/imagetool-setup/jars/p28186730_139425_Generic.zip + [INFO ] Updating OPatch in final image from version 13.9.4.2.1 to version 13.9.4.2.5 + [WARNING] Skipping patch conflict check, no support credentials provided + [WARNING] No credentials provided, skipping validation of patches + [INFO ] Using patch 32224021_12.2.1.4 from cache: /home/asirasag/imagetool-setup/jars/p32224021_122140_Generic.zip + [INFO ] docker cmd = docker build --no-cache --force-rm --tag wcportal:12.2.1.4-32224021 --build-arg http_proxy=http://www-proxy.us.oracle.com:80 --build-arg https_proxy=http://www-proxy.us.oracle.com:80 --build-arg no_proxy=localhost,127.0.0.0/8,.us.oracle.com,.oraclecorp.com,/var/run/docker.sock,100.111.157.155 /scratch/asirasag/imagetoolcache/builddir/wlsimgbuilder_temp5130105621506307568 + Sending build context to Docker daemon 192.4MB + + Step 1/9 : FROM oracle/wcportal:12.2.1.4 as final_build + ---> 5592ff7e5a02 + Step 2/9 : USER root + ---> Running in 0b3ff2600f11 + Removing intermediate container 0b3ff2600f11 + ---> faad3a32f39c + Step 3/9 : ENV OPATCH_NO_FUSER=true + ---> Running in 2beab0bfe88b + Removing intermediate container 2beab0bfe88b + ---> 6fd9e1664818 + Step 4/9 : LABEL com.oracle.weblogic.imagetool.buildid="50f9b9aa-596c-4bae-bdff-c47c16b4c928" + ---> Running in 9a5f8fc172c9 + Removing intermediate container 9a5f8fc172c9 + ---> 499620a1f857 + Step 5/9 : USER oracle + ---> Running in fe28af056858 + Removing intermediate container fe28af056858 + ---> 3507971c35d5 + Step 6/9 : COPY --chown=oracle:oracle p28186730_139425_Generic.zip /tmp/imagetool/opatch/ + ---> c44c3c7b17f7 + Step 7/9 : RUN cd /tmp/imagetool/opatch && /u01/jdk/bin/jar -xf /tmp/imagetool/opatch/p28186730_139425_Generic.zip && /u01/jdk/bin/java -jar /tmp/imagetool/opatch/6880880/opatch_generic.jar -silent -ignoreSysPrereqs -force -novalidation oracle_home=/u01/oracle && rm -rf /tmp/imagetool + ---> Running in 8380260fe62d + Launcher log file is /tmp/OraInstall2021-04-08_05-18-14AM/launcher2021-04-08_05-18-14AM.log. + Extracting the installer . . . . Done + Checking if CPU speed is above 300 MHz. Actual 2195.098 MHz Passed + Checking swap space: must be greater than 512 MB. Actual 14999 MB Passed + Checking if this platform requires a 64-bit JVM. Actual 64 Passed (64-bit not required) + Checking temp space: must be greater than 300 MB. Actual 152772 MB Passed + Preparing to launch the Oracle Universal Installer from /tmp/OraInstall2021-04-08_05-18-14AM + Installation Summary + + + Disk Space : Required 34 MB, Available 152,736 MB + Feature Sets to Install: + Next Generation Install Core 13.9.4.0.1 + OPatch 13.9.4.2.5 + OPatch Auto OPlan 13.9.4.2.5 + Session log file is /tmp/OraInstall2021-04-08_05-18-14AM/install2021-04-08_05-18-14AM.log + + Loading products list. Please wait. + 1% + 40% + + Loading products. Please wait. + + 98% + 99% + + Updating Libraries + + Starting Installations + 1% + 94% + 95% + 96% + + Install pending + + Installation in progress + + Component : oracle.glcm.logging 1.6.4.0.0 + + Copying files for oracle.glcm.logging 1.6.4.0.0 + + Component : oracle.glcm.comdev 7.8.4.0.0 + + Copying files for oracle.glcm.comdev 7.8.4.0.0 + + Component : oracle.glcm.dependency 1.8.4.0.0 + + Copying files for oracle.glcm.dependency 1.8.4.0.0 + + Component : oracle.glcm.xmldh 3.4.4.0.0 + + Copying files for oracle.glcm.xmldh 3.4.4.0.0 + + Component : oracle.glcm.wizard 7.8.4.0.0 + + Copying files for oracle.glcm.wizard 7.8.4.0.0 + + Component : oracle.glcm.opatch.common.api 13.9.4.0.0 + + Copying files for oracle.glcm.opatch.common.api 13.9.4.0.0 + + Component : oracle.nginst.common 13.9.4.0.0 + + Copying files for oracle.nginst.common 13.9.4.0.0 + + Component : oracle.nginst.core 13.9.4.0.0 + + Copying files for oracle.nginst.core 13.9.4.0.0 + + Component : oracle.glcm.encryption 2.7.4.0.0 + + Copying files for oracle.glcm.encryption 2.7.4.0.0 + + Component : oracle.swd.opatch 13.9.4.2.5 + + Copying files for oracle.swd.opatch 13.9.4.2.5 + + Component : oracle.glcm.osys.core 13.9.1.0.0 + + Copying files for oracle.glcm.osys.core 13.9.1.0.0 + + Component : oracle.glcm.oplan.core 13.9.4.2.0 + + Copying files for oracle.glcm.oplan.core 13.9.4.2.0 + + Install successful + + Post feature install pending + + Post Feature installing + + Feature Set : glcm_common_lib + + Feature Set : glcm_common_logging_lib + + Post Feature installing glcm_common_lib + + Post Feature installing glcm_common_logging_lib + + Feature Set : commons-cli_1.3.1.0.0 + + Post Feature installing commons-cli_1.3.1.0.0 + + Feature Set : oracle.glcm.opatch.common.api.classpath + + Post Feature installing oracle.glcm.opatch.common.api.classpath + + Feature Set : glcm_encryption_lib + + Post Feature installing glcm_encryption_lib + + Feature Set : oracle.glcm.osys.core.classpath + + Post Feature installing oracle.glcm.osys.core.classpath + + Feature Set : oracle.glcm.oplan.core.classpath + + Post Feature installing oracle.glcm.oplan.core.classpath + + Feature Set : oracle.glcm.opatchauto.core.classpath + + Post Feature installing oracle.glcm.opatchauto.core.classpath + + Feature Set : oracle.glcm.opatchauto.core.binary.classpath + + Post Feature installing oracle.glcm.opatchauto.core.binary.classpath + + Feature Set : oracle.glcm.opatchauto.core.actions.classpath + + Post Feature installing oracle.glcm.opatchauto.core.actions.classpath + + Feature Set : oracle.glcm.opatchauto.core.wallet.classpath + + Post Feature installing oracle.glcm.opatchauto.core.wallet.classpath + + Post feature install complete + + String substitutions pending + + String substituting + + Component : oracle.glcm.logging 1.6.4.0.0 + + String substituting oracle.glcm.logging 1.6.4.0.0 + + Component : oracle.glcm.comdev 7.8.4.0.0 + + String substituting oracle.glcm.comdev 7.8.4.0.0 + + Component : oracle.glcm.dependency 1.8.4.0.0 + + String substituting oracle.glcm.dependency 1.8.4.0.0 + + Component : oracle.glcm.xmldh 3.4.4.0.0 + + String substituting oracle.glcm.xmldh 3.4.4.0.0 + + Component : oracle.glcm.wizard 7.8.4.0.0 + + String substituting oracle.glcm.wizard 7.8.4.0.0 + + Component : oracle.glcm.opatch.common.api 13.9.4.0.0 + + String substituting oracle.glcm.opatch.common.api 13.9.4.0.0 + + Component : oracle.nginst.common 13.9.4.0.0 + + String substituting oracle.nginst.common 13.9.4.0.0 + + Component : oracle.nginst.core 13.9.4.0.0 + + String substituting oracle.nginst.core 13.9.4.0.0 + + Component : oracle.glcm.encryption 2.7.4.0.0 + + String substituting oracle.glcm.encryption 2.7.4.0.0 + + Component : oracle.swd.opatch 13.9.4.2.5 + + String substituting oracle.swd.opatch 13.9.4.2.5 + + Component : oracle.glcm.osys.core 13.9.1.0.0 + + String substituting oracle.glcm.osys.core 13.9.1.0.0 + + Component : oracle.glcm.oplan.core 13.9.4.2.0 + + String substituting oracle.glcm.oplan.core 13.9.4.2.0 + + String substitutions complete + + Link pending + + Linking in progress + + Component : oracle.glcm.logging 1.6.4.0.0 + + Linking oracle.glcm.logging 1.6.4.0.0 + + Component : oracle.glcm.comdev 7.8.4.0.0 + + Linking oracle.glcm.comdev 7.8.4.0.0 + + Component : oracle.glcm.dependency 1.8.4.0.0 + + Linking oracle.glcm.dependency 1.8.4.0.0 + + Component : oracle.glcm.xmldh 3.4.4.0.0 + + Linking oracle.glcm.xmldh 3.4.4.0.0 + + Component : oracle.glcm.wizard 7.8.4.0.0 + + Linking oracle.glcm.wizard 7.8.4.0.0 + + Component : oracle.glcm.opatch.common.api 13.9.4.0.0 + + Linking oracle.glcm.opatch.common.api 13.9.4.0.0 + + Component : oracle.nginst.common 13.9.4.0.0 + + Linking oracle.nginst.common 13.9.4.0.0 + + Component : oracle.nginst.core 13.9.4.0.0 + + Linking oracle.nginst.core 13.9.4.0.0 + + Component : oracle.glcm.encryption 2.7.4.0.0 + + Linking oracle.glcm.encryption 2.7.4.0.0 + + Component : oracle.swd.opatch 13.9.4.2.5 + + Linking oracle.swd.opatch 13.9.4.2.5 + + Component : oracle.glcm.osys.core 13.9.1.0.0 + + Linking oracle.glcm.osys.core 13.9.1.0.0 + + Component : oracle.glcm.oplan.core 13.9.4.2.0 + + Linking oracle.glcm.oplan.core 13.9.4.2.0 + + Linking in progress + + Link successful + + Setup pending + + Setup in progress + + Component : oracle.glcm.logging 1.6.4.0.0 + + Setting up oracle.glcm.logging 1.6.4.0.0 + + Component : oracle.glcm.comdev 7.8.4.0.0 + + Setting up oracle.glcm.comdev 7.8.4.0.0 + + Component : oracle.glcm.dependency 1.8.4.0.0 + + Setting up oracle.glcm.dependency 1.8.4.0.0 + + Component : oracle.glcm.xmldh 3.4.4.0.0 + + Setting up oracle.glcm.xmldh 3.4.4.0.0 + + Component : oracle.glcm.wizard 7.8.4.0.0 + + Setting up oracle.glcm.wizard 7.8.4.0.0 + + Component : oracle.glcm.opatch.common.api 13.9.4.0.0 + + Setting up oracle.glcm.opatch.common.api 13.9.4.0.0 + + Component : oracle.nginst.common 13.9.4.0.0 + + Setting up oracle.nginst.common 13.9.4.0.0 + + Component : oracle.nginst.core 13.9.4.0.0 + + Setting up oracle.nginst.core 13.9.4.0.0 + + Component : oracle.glcm.encryption 2.7.4.0.0 + + Setting up oracle.glcm.encryption 2.7.4.0.0 + + Component : oracle.swd.opatch 13.9.4.2.5 + + Setting up oracle.swd.opatch 13.9.4.2.5 + + Component : oracle.glcm.osys.core 13.9.1.0.0 + + Setting up oracle.glcm.osys.core 13.9.1.0.0 + + Component : oracle.glcm.oplan.core 13.9.4.2.0 + + Setting up oracle.glcm.oplan.core 13.9.4.2.0 + + Setup successful + + Save inventory pending + + Saving inventory + 97% + + Saving inventory complete + 98% + + Configuration complete + + Component : glcm_common_logging_lib + + Saving the inventory glcm_common_logging_lib + + Component : glcm_encryption_lib + + Component : oracle.glcm.opatch.common.api.classpath + + Saving the inventory oracle.glcm.opatch.common.api.classpath + + Saving the inventory glcm_encryption_lib + + Component : cieCfg_common_rcu_lib + + Component : glcm_common_lib + + Saving the inventory cieCfg_common_rcu_lib + + Saving the inventory glcm_common_lib + + Component : oracle.glcm.logging + + Saving the inventory oracle.glcm.logging + + Component : cieCfg_common_lib + + Saving the inventory cieCfg_common_lib + + Component : svctbl_lib + + Saving the inventory svctbl_lib + + Component : com.bea.core.binxml_dependencies + + Saving the inventory com.bea.core.binxml_dependencies + + Component : svctbl_jmx_client + + Saving the inventory svctbl_jmx_client + + Component : cieCfg_wls_shared_lib + + Saving the inventory cieCfg_wls_shared_lib + + Component : rcuapi_lib + + Saving the inventory rcuapi_lib + + Component : rcu_core_lib + + Saving the inventory rcu_core_lib + + Component : cieCfg_wls_lib + + Saving the inventory cieCfg_wls_lib + + Component : cieCfg_wls_external_lib + + Saving the inventory cieCfg_wls_external_lib + + Component : cieCfg_wls_impl_lib + + Saving the inventory cieCfg_wls_impl_lib + + Component : rcu_dependencies_lib + + Saving the inventory rcu_dependencies_lib + + Component : oracle.fmwplatform.fmwprov_lib + + Saving the inventory oracle.fmwplatform.fmwprov_lib + + Component : fmwplatform-wlst-dependencies + + Saving the inventory fmwplatform-wlst-dependencies + + Component : oracle.fmwplatform.ocp_lib + + Saving the inventory oracle.fmwplatform.ocp_lib + + Component : oracle.fmwplatform.ocp_plugin_lib + + Saving the inventory oracle.fmwplatform.ocp_plugin_lib + + Component : wlst.wls.classpath + + Saving the inventory wlst.wls.classpath + + Component : maven.wls.classpath + + Saving the inventory maven.wls.classpath + + Component : com.oracle.webservices.fmw.ws-assembler + + Saving the inventory com.oracle.webservices.fmw.ws-assembler + + Component : sdpmessaging_dependencies + + Saving the inventory sdpmessaging_dependencies + + Component : sdpclient_dependencies + + Saving the inventory sdpclient_dependencies + + Component : com.oracle.jersey.fmw.client + + Saving the inventory com.oracle.jersey.fmw.client + + Component : com.oracle.webservices.fmw.client + + Saving the inventory com.oracle.webservices.fmw.client + + Component : oracle.jrf.wls.classpath + + Saving the inventory oracle.jrf.wls.classpath + + Component : oracle.jrf.wlst + + Saving the inventory oracle.jrf.wlst + + Component : fmwshare-wlst-dependencies + + Saving the inventory fmwshare-wlst-dependencies + + Component : oracle.fmwshare.pyjar + + Saving the inventory oracle.fmwshare.pyjar + + Component : com.oracle.webservices.wls.jaxws-owsm-client + + Saving the inventory com.oracle.webservices.wls.jaxws-owsm-client + + Component : glcm_common_logging_lib + + Component : glcm_common_lib + + Saving the inventory glcm_common_lib + + Component : glcm_encryption_lib + + Saving the inventory glcm_encryption_lib + + Component : oracle.glcm.opatch.common.api.classpath + + Saving the inventory oracle.glcm.opatch.common.api.classpath + + Component : cieCfg_common_rcu_lib + + Saving the inventory cieCfg_common_rcu_lib + + Saving the inventory glcm_common_logging_lib + + Component : oracle.glcm.logging + + Saving the inventory oracle.glcm.logging + + Component : cieCfg_common_lib + + Saving the inventory cieCfg_common_lib + + Component : svctbl_lib + + Saving the inventory svctbl_lib + + Component : com.bea.core.binxml_dependencies + + Saving the inventory com.bea.core.binxml_dependencies + + Component : svctbl_jmx_client + + Saving the inventory svctbl_jmx_client + + Component : cieCfg_wls_shared_lib + + Saving the inventory cieCfg_wls_shared_lib + + Component : rcuapi_lib + + Saving the inventory rcuapi_lib + + Component : rcu_core_lib + + Saving the inventory rcu_core_lib + + Component : cieCfg_wls_lib + + Saving the inventory cieCfg_wls_lib + + Component : cieCfg_wls_external_lib + + Saving the inventory cieCfg_wls_external_lib + + Component : cieCfg_wls_impl_lib + + Saving the inventory cieCfg_wls_impl_lib + + Component : soa_com.bea.core.binxml_dependencies + + Saving the inventory soa_com.bea.core.binxml_dependencies + + Component : glcm_common_logging_lib + + Saving the inventory glcm_common_logging_lib + + Component : glcm_common_lib + + Saving the inventory glcm_common_lib + + Component : glcm_encryption_lib + + Saving the inventory glcm_encryption_lib + + Component : oracle.glcm.opatch.common.api.classpath + + Component : oracle.glcm.oplan.core.classpath + + Saving the inventory oracle.glcm.oplan.core.classpath + + Saving the inventory oracle.glcm.opatch.common.api.classpath + + The install operation completed successfully. + + Logs successfully copied to /u01/oracle/.inventory/logs. + Removing intermediate container 8380260fe62d + ---> d57be7ffa162 + Step 8/9 : COPY --chown=oracle:oracle patches/* /tmp/imagetool/patches/ + ---> dd421aae5aaf + Step 9/9 : RUN /u01/oracle/OPatch/opatch napply -silent -oh /u01/oracle -phBaseDir /tmp/imagetool/patches && test $? -eq 0 && /u01/oracle/OPatch/opatch util cleanup -silent -oh /u01/oracle || (cat /u01/oracle/cfgtoollogs/opatch/opatch*.log && exit 1) + ---> Running in 323e7ae70339 + Oracle Interim Patch Installer version 13.9.4.2.5 + Copyright (c) 2021, Oracle Corporation. All rights reserved. + + + Oracle Home : /u01/oracle + Central Inventory : /u01/oracle/.inventory + from : /u01/oracle/oraInst.loc + OPatch version : 13.9.4.2.5 + OUI version : 13.9.4.0.0 + Log file location : /u01/oracle/cfgtoollogs/opatch/opatch2021-04-08_05-20-25AM_1.log + + + OPatch detects the Middleware Home as "/u01/oracle" + + Verifying environment and performing prerequisite checks... + OPatch continues with these patches: 32224021 + + Do you want to proceed? [y|n] + Y (auto-answered by -silent) + User Responded with: Y + All checks passed. + + Please shutdown Oracle instances running out of this ORACLE_HOME on the local system. + (Oracle Home = '/u01/oracle') + + + Is the local system ready for patching? [y|n] + Y (auto-answered by -silent) + User Responded with: Y + Backing up files... + Applying interim patch '32224021' to OH '/u01/oracle' + ApplySession: Optional component(s) [ oracle.webcenter.sca, 12.2.1.4.0 ] , [ oracle.webcenter.sca, 12.2.1.4.0 ] , [ oracle.webcenter.ucm, 12.2.1.4.0 ] , [ oracle.webcenter.ucm, 12.2.1.4.0 ] not present in the Oracle Home or a higher version is found. + + Patching component oracle.webcenter.portal, 12.2.1.4... + + Patching component oracle.webcenter.portal, 12.2.1.4... + + Patching component oracle.rcu.webcenter.portal, 12.2.1.0... + + Patching component oracle.rcu.webcenter.portal, 12.2.1.0... + Patch 32224021 successfully applied. + Log file location: /u01/oracle/cfgtoollogs/opatch/opatch2021-04-08_05-20-25AM_1.log + + OPatch succeeded. + Oracle Interim Patch Installer version 13.9.4.2.5 + Copyright (c) 2021, Oracle Corporation. All rights reserved. + + + Oracle Home : /u01/oracle + Central Inventory : /u01/oracle/.inventory + from : /u01/oracle/oraInst.loc + OPatch version : 13.9.4.2.5 + OUI version : 13.9.4.0.0 + Log file location : /u01/oracle/cfgtoollogs/opatch/opatch2021-04-08_05-27-11AM_1.log + + + OPatch detects the Middleware Home as "/u01/oracle" + + Invoking utility "cleanup" + OPatch will clean up 'restore.sh,make.txt' files and 'scratch,backup' directories. + You will be still able to rollback patches after this cleanup. + Do you want to proceed? [y|n] + Y (auto-answered by -silent) + User Responded with: Y + + Backup area for restore has been cleaned up. For a complete list of files/directories + deleted, Please refer log file. + + OPatch succeeded. + Removing intermediate container 323e7ae70339 + ---> 0e7c514dcf7b + Successfully built 0e7c514dcf7b + Successfully tagged wcportal:12.2.1.4-32224021 + [INFO ] Build successful. Build time=645s. Image tag=wcportal:12.2.1.4-32224021 + + {{% /expand %}} + + + {{%expand "Click here to see the example Dockerfile generated by the WebLogic Image Tool with the --dryRun option:" %}} + + $ imagetool update --fromImage oracle/wcportal:12.2.1.4 --tag=wcportal:12.2.1.4-30761841 --patches=30761841_12.2.1.4.0 --dryRun + [INFO ] Image Tool build ID: a473ba32-84b6-4374-9425-9e92ac90ee87 + [INFO ] Temporary directory used for docker build context: /scratch/asirasag/imagetoolcache/builddir/wlsimgbuilder_temp874401188519547557 + [INFO ] Using patch 28186730_13.9.4.2.5 from cache: /home/asirasag/imagetool-setup/jars/p28186730_139425_Generic.zip + [INFO ] Updating OPatch in final image from version 13.9.4.2.1 to version 13.9.4.2.5 + [WARNING] Skipping patch conflict check, no support credentials provided + [WARNING] No credentials provided, skipping validation of patches + [INFO ] Using patch 32224021_12.2.1.4 from cache: /home/asirasag/imagetool-setup/jars/p32224021_122140_Generic.zip + [INFO ] docker cmd = docker build --no-cache --force-rm --tag wcportal:12.2.1.4-32224021 --build-arg http_proxy=http://www-proxy.us.oracle.com:80 --build-arg https_proxy=http://www-proxy.us.oracle.com:80 --build-arg no_proxy=localhost,127.0.0.0/8,.us.oracle.com,.oraclecorp.com,/var/run/docker.sock,100.111.157.155 /scratch/asirasag/imagetoolcache/builddir/wlsimgbuilder_temp874401188519547557 + ########## BEGIN DOCKERFILE ########## + # + # Copyright (c) 2019, 2021, Oracle and/or its affiliates. + # + # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + # + # + + FROM oracle/wcportal:12.2.1.4 as final_build + USER root + + ENV OPATCH_NO_FUSER=true + + + LABEL com.oracle.weblogic.imagetool.buildid="a473ba32-84b6-4374-9425-9e92ac90ee87" + + USER oracle + + COPY --chown=oracle:oracle p28186730_139425_Generic.zip /tmp/imagetool/opatch/ + RUN cd /tmp/imagetool/opatch \ + && /u01/jdk/bin/jar -xf /tmp/imagetool/opatch/p28186730_139425_Generic.zip \ + && /u01/jdk/bin/java -jar /tmp/imagetool/opatch/6880880/opatch_generic.jar -silent -ignoreSysPrereqs -force -novalidation oracle_home=/u01/oracle \ + && rm -rf /tmp/imagetool + + COPY --chown=oracle:oracle patches/* /tmp/imagetool/patches/ + + # Apply all patches provided at the same time + RUN /u01/oracle/OPatch/opatch napply -silent -oh /u01/oracle -phBaseDir /tmp/imagetool/patches \ + && test $? -eq 0 \ + && /u01/oracle/OPatch/opatch util cleanup -silent -oh /u01/oracle \ + || (cat /u01/oracle/cfgtoollogs/opatch/opatch*.log && exit 1) + + ########## END DOCKERFILE ########## + + + {{% /expand %}} + + +1. Check the built image using the `docker images` command: + ```bash + $ docker images | grep wcportal + wcportal 12.2.1.4-30761841 + 2ef2a67a685b About a minute ago 3.58GB + $ + ``` + +### Create an Oracle WebCenter Portal Docker image using Dockerfile + +For test and development purposes, you can create an Oracle WebCenter Portal image using the Dockerfile. Consult the [README](https://github.com/oracle/docker-images/blob/master/OracleWebCenterPortal/dockerfiles/README.md) file for important prerequisite steps, +such as building or pulling the Server JRE Docker image, Oracle Fusion Middleware Infrastructure Docker image and downloading the Oracle WebCenter Portal installer and bundle patch binaries. + +A prebuilt Oracle Fusion Middleware Infrastructure image, `container-registry.oracle.com/middleware/fmw-infrastructure:12.2.1.4`, is available at `container-registry.oracle.com`. We recommend that you pull and rename this image to build the Oracle WebCenter Portal image. + + + ```bash + $ docker pull container-registry.oracle.com/middleware/fmw-infrastructure:12.2.1.4 + $ docker tag container-registry.oracle.com/middleware/fmw-infrastructure:12.2.1.4 oracle/fmw-infrastructure:12.2.1.4 + ``` +To build an Oracle Fusion Middleware Infrastructure image and on top of that the Oracle WebCenter Portal image as a layer, follow these steps: + +1. Make a local clone of the sample repository: + + ```bash + $ git clone https://github.com/oracle/docker-images + ``` + +1. Download the Oracle WebCenter Portal installer from the Oracle Technology Network or e-delivery. + + >Note: Copy the installer binaries to the same location as the Dockerfile. + +1. Create the Oracle WebCenter Portal image by running the provided script: + + ```bash + $ cd docker-images/OracleWebCenterPortal/dockerfiles + $ ./buildDockerImage.sh -v 12.2.1.4 -s + ``` + The image produced is named `oracle/wcportal:12.2.1.4`. The samples and instructions assume the Oracle WebCenter Portal image is named `oracle/wcportal:12.2.1.4`. You must rename your image to match this name, or update the samples to refer to the image you created. \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/installguide/_index.md b/docs-source/content/wcportal-domains/installguide/_index.md new file mode 100644 index 000000000..b82c94d49 --- /dev/null +++ b/docs-source/content/wcportal-domains/installguide/_index.md @@ -0,0 +1,11 @@ ++++ +title = "Install Guide" +date = 2020-06-18T15:27:48-05:00 +weight = 2 +pre = "2. " ++++ + + +Install the WebLogic Kubernetes operator and prepare and deploy the Oracle WebCenter Portal domain. + +{{% children style="h4" description="true" %}} \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/installguide/configure-wcp-search/_index.md b/docs-source/content/wcportal-domains/installguide/configure-wcp-search/_index.md new file mode 100644 index 000000000..fc7315aac --- /dev/null +++ b/docs-source/content/wcportal-domains/installguide/configure-wcp-search/_index.md @@ -0,0 +1,266 @@ ++++ +title = "Configure WebCenter Portal For Search" +weight = 4 +pre = " " +description = "Set up search functionality in Oracle WebCenter Portal using Elasticsearch." ++++ + +* [Introduction](#introduction) +* [Set Up Persistent Volume and Persistent Volume Claim](#set-up-persistent-volume-and-persistent-volume-claim ) +* [Create a Secret](#create-a-secret) +* [Headless Service](#headless-service) +* [LoadBalancer](#loadbalancer) +* [LoadBalancer Validation](#loadbalancer-validation) +* [Elasticsearch Cluster](#elasticsearch-cluster) +* [Deployment Validation](#deployment-validation) + +#### Introduction +Elasticsearch is a highly scalable search engine. It allows you to store, search, and analyze big volumes of data quickly and provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON document. + +#### Set Up Persistent Volume and Persistent Volume Claim +Create a Kubernetes PV and PVC (Persistent Volume and Persistent Volume Claim) to store Elasticsearch data. To create PV and PVC, use the deployment YAML configuration file located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-pvpvc.yaml`. + +```yaml +apiVersion: v1 +kind: PersistentVolume +metadata: + name: es-data-pv + namespace: wcpns +spec: + storageClassName: es-data-pv-storage-class + capacity: + storage: 10Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + hostPath: + path: "/scratch/esdata" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: es-data-pvc + namespace: wcpns +spec: + storageClassName: es-data-pv-storage-class + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Gi +``` +To create PV & PVC run the below command: +```bash +$ kubectl apply -f es-pvpvc.yaml +``` +#### Create a Secret +To grant access to Oracle WebCenter Portal, create a Kubernetes secret using the deployment YAML configuration file located at `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-secret.yaml` + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: es-secret + namespace: wcpns +data: + # base64 encoded strings + wls-admin: d2VibG9naWM= + wls-admin-pwd: d2VsY29tZTE= + search-admin: d2NjcmF3bGFkbWlu + search-admin-pwd: d2VsY29tZTE= + ``` + Where: + wls-admin :Oracle WebCenter Admin UserName + wls-admin-pwd :Oracle WebCenter Admin Password + search-admin :ElasticSearch Username + search-admin-pwd : ElasticSearch Password +To create Kubernetes Secret run the below command: +```bash +$ kubectl apply -f es-secret.yaml +``` +#### Headless Service + Each node in Elasticsearch cluster can communicate using a headless service. Create a headless service using the deployment YAML configuration file located at `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-service.yaml` to establish cluster communication. + ```yaml +apiVersion: v1 +kind: Service +metadata: + name: es-svc + namespace: wcpns + labels: + service: elasticsearch +spec: + # headless service + clusterIP: None + ports: + - port: 9200 + name: http + - port: 9300 + name: transport + selector: + service: elasticsearch +``` +To create Headless Service run below command: +```bash +$ kubectl apply -f es-service.yaml +``` +### LoadBalancer +To access the Elasticsearch service outside of the Kubernetes cluster, create an external loadbalancer. Then access the Elasticsearch service by using the external IP of loadbalancer, create a loadbalancer using the deployment YAML configuration file located at `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-loadbalancer.yaml`. +```yaml +apiVersion: v1 +kind: Service +metadata: + name: es-loadbalancer + namespace: wcpns + labels: + type: external +spec: + type: LoadBalancer + selector: + service: elasticsearch + ports: + - name: http + port: 9200 + targetPort: 9200 +``` +To create a loadbalancer run below command: +```bash +$ kubectl apply -f es-loadbalancer.yaml +``` +#### LoadBalancer Validation +Once the loadbalancer is successfully deployed, validate it by running the following command: + +```bash +$ kubectl get svc -n wcpns -l type=external +``` +Make a note of the external IP from the above command and use this below sample URL to access Elasticsearch cluster health : http://externalIP:9200/_cluster/health + #### Elasticsearch Cluster + Using the Kubernetes StatefulSet controller create an Elasticsearch Cluster comprising of three node using the deployment YAML configuration file located at `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-statefulset.yaml` + +```yaml +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: es-statefulset + namespace: wcpns + labels: + service: elasticsearch +spec: + serviceName: es-svc + replicas: 1 + selector: + matchLabels: + service: elasticsearch + template: + metadata: + labels: + service: elasticsearch + spec: + initContainers: + - name: increase-the-vm-max-map-count + image: busybox + command: + - sysctl + - -w + - vm.max_map_count=262144 + securityContext: + privileged: true + - name: increase-the-ulimit + image: busybox + command: + - sh + - -c + - ulimit -n 65536 + securityContext: + privileged: true + volumes: + - name: es-node + persistentVolumeClaim: + claimName: es-data-pvc + - name: wcp-domain + persistentVolumeClaim: + claimName: wcp-domain-domain-pvc + containers: + - name: es-container + image: oracle/wcportal:12.2.1.4 + imagePullPolicy: IfNotPresent + command: [ "/bin/sh", "-c", "/u01/oracle/container-scripts/configureOrStartElasticsearch.sh" ] + readinessProbe: + httpGet: + path: / + port: 9200 + httpHeaders: + - name: Authorization + value: Basic d2NjcmF3bGFkbWluOndlbGNvbWUx + initialDelaySeconds: 150 + periodSeconds: 30 + timeoutSeconds: 10 + successThreshold: 1 + failureThreshold: 10 + lifecycle: + preStop: + exec: + command: [ "/bin/sh", "-c", "/u01/oracle/container-scripts/elasticsearchPreStopHandler.sh" ] + ports: + - containerPort: 9200 + name: http + - containerPort: 9300 + name: tcp + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: UNICAST_HOST_LIST + value: "es-svc" + - name: ADMIN_USERNAME + valueFrom: + secretKeyRef: + name: es-secret + key: wls-admin + - name: ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: es-secret + key: wls-admin-pwd + - name: SEARCH_APP_USERNAME + valueFrom: + secretKeyRef: + name: es-secret + key: search-admin + - name: SEARCH_APP_USER_PASSWORD + valueFrom: + secretKeyRef: + name: es-secret + key: search-admin-pwd + - name: ADMIN_SERVER_CONTAINER_NAME + value: wcp-domain-adminserver + - name: ADMIN_PORT + value: "7001" + - name: ES_CLUSTER_NAME + value: es-cluster + - name: DOMAIN_NAME + value: wcp-domain + - name: CONFIGURE_ES_CONNECTION + value: "true" + - name: LOAD_BALANCER_IP + value: "es-loadbalancer.wcpns.svc.cluster.local" + volumeMounts: + - name: es-node + mountPath: /u01/esHome/esNode + - name: wcp-domain + mountPath: /u01/oracle/user_projects/domains +``` +>Note: The values used for ADMIN_PORT and Image name should be same as values passed to `create-domain.sh` job while creating domain. + +To create a es-statefulset run below command: +```bash +$ kubectl apply -f es-statefulset.yaml +``` +>Note: After setting up Elasticsearch cluster restart all the instance of Oracle WebCenter Portal server. +#### Deployment Validation +Validate the deployment by running the following command: +```bash +$ kubectl get pods -n wcpns -l service=elasticsearch +``` + + diff --git a/docs-source/content/wcportal-domains/installguide/create-wcp-domain/_index.md b/docs-source/content/wcportal-domains/installguide/create-wcp-domain/_index.md new file mode 100644 index 000000000..8e6d922f2 --- /dev/null +++ b/docs-source/content/wcportal-domains/installguide/create-wcp-domain/_index.md @@ -0,0 +1,392 @@ ++++ +title = "Create WebCenter Portal domain" +weight = 3 +pre = " " +description = "Create an Oracle WebCenter Portal domain home on an existing PV or PVC, and create the domain resource YAML file for deploying the generated Oracle WebCenter Portal domain." ++++ + +#### Contents + +* [Introduction](#introduction) +* [Prerequisites](#prerequisites) +* [Prepare the WebCenter Portal Domain Creation Input File](#prepare-the-webcenter-portal-domain-creation-input-file) +* [Create the WebCenter Portal Domain](#create-the-webcenter-portal-domain) +* [Initialize the WebCenter Portal Domain](#initialize-the-webcenter-portal-domain) +* [Verify the WebCenter Portal Domain](#verify-the-webcenter-portal-domain) +* [Managing WebCenter Portal](#managing-webcenter-portal) + + +#### Introduction + +You can use the sample scripts to create a WebCenter Portal domain home on an existing Kubernetes persistent volume (PV) and persistent volume claim (PVC).The scripts also generate the domain YAML file, which helps you start the Kubernetes artifacts of the corresponding domain. + +#### Prerequisites + +* Ensure that you have completed all of the steps under [prepare-your-environment]({{< relref "/wcportal-domains/prepare-your-environment/_index.md">}}). +* Ensure that the database and the WebLogic Kubernetes operator is up. + +#### Prepare the WebCenter Portal Domain Creation Input File + +If required, you can customize the parameters used for creating a domain in the `create-domain-inputs.yaml` file. + +Please note that the sample scripts for the WebCenter Portal domain deployment are available from the previously downloaded repository at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv/`. + +Make a copy of the `create-domain-inputs.yaml` file before updating the default values. + +The default domain created by the script has the following characteristics: + +* An Administration Server named `AdminServer` listening on port `7001`. +* A configured cluster named `wcp-cluster` of size `5`. +* Managed Server, named `wcpserver`, listening on port `8888`. +* Log files that are located in `/shared/logs/`. + +##### Configuration parameters +The following parameters can be provided in the inputs file: + +| Parameter | Definition | Default | +| --- | --- | --- | +| `adminPort` | Port number for the Administration Server inside the Kubernetes cluster. | `7001` | +| `sslEnabled` | SSL mode enabling flag | `false` | +| `adminServerSSLPort` | SSL Port number for the Administration Server inside the Kubernetes cluster. | `7002` | +| `adminServerName` | Name of the Administration Server. | `AdminServer` | +| `clusterName` | Name of the WebLogic cluster instance to generate for the domain. By default the cluster name is `wcp-cluster` for the WebCenter Portal domain. | `wcp-cluster` | +| `configuredManagedServerCount` | Number of Managed Server instances for the domain. | `5` | +| `createDomainFilesDir` | Directory on the host machine to locate all the files that you need to create a WebLogic domain, including the script that is specified in the `createDomainScriptName` property. By default, this directory is set to the relative path `wlst`, and the *create script* uses the built-in WLST offline scripts in the `wlst` directory to create the WebLogic domain. An absolute path is also supported to point to an arbitrary directory in the file system. The built-in scripts can be replaced by the user-provided scripts or model files as long as those files are in the specified directory. Files in this directory are put into a Kubernetes config map, which in turn is mounted to `createDomainScriptsMountPath,` so that the Kubernetes pod can use the scripts and supporting files to create a domain home. | `wlst` | +| `createDomainScriptsMountPath` | Mount path where the *create domain* scripts are located inside a pod. The `create-domain.sh` script creates a Kubernetes job to run the script (specified in the `createDomainScriptName` property) in a Kubernetes pod that creates a domain home. Files in the `createDomainFilesDir` directory are mounted to this location in the pod, so that the Kubernetes pod can use the scripts and supporting files to create a domain home. | `/u01/weblogic` | +| `createDomainScriptName` | Script that the *create domain* script uses to create a WebLogic domain. The `create-domain.sh` script creates a Kubernetes job to run this script that creates a domain home. The script is located in the *in-pod* directory that is specified in the `createDomainScriptsMountPath` property. If you need to provide your own scripts to create the domain home, instead of using the built-in scripts, you must use this property to set the name of the script to that which you want the *create* domain job to run. | `create-domain-job.sh` | +| `domainHome` | Home directory of the WebCenter Portal domain. `This field cannot be modified.` | `/u01/oracle/user_projects/domains/wcp-domain` | +| `domainPVMountPath` | Mount path of the domain persistent volume. `This field cannot be modified.` | `/u01/oracle/user_projects/domains` | +| `domainUID` | Unique ID that identifies this particular domain. Used as the name of the generated WebLogic domain as well as the name of the Kubernetes domain resource. This ID must be unique across all domains in a Kubernetes cluster. This ID cannot contain any character that is not valid in a Kubernetes service name. | `wcp-domain` | +| `exposeAdminNodePort` | Boolean indicating if the Administration Server is exposed outside of the Kubernetes cluster. | `false` | +| `exposeAdminT3Channel` | Boolean indicating if the T3 administrative channel is exposed outside the Kubernetes cluster. | `false` | +| `image` | WebCenter Portal Docker image. The WebLogic Kubernetes Operator requires WebCenter Portal release 12.2.1.4. Refer to [WebCenter Portal Docker Image](https://github.com/oracle/docker-images/tree/master/OracleWebCenterPortal) for details on how to obtain or create the image. | `oracle/wcportal:12.2.1.4` | +| `imagePullPolicy` | WebLogic Docker image pull policy. Legal values are `IfNotPresent`, `Always`, or `Never` | `IfNotPresent` | +| `imagePullSecretName` | Name of the Kubernetes secret to access the Docker Store to pull the WebLogic Server Docker image. The presence of the secret is validated when this parameter is specified. | | +| `includeServerOutInPodLog` | Boolean indicating whether to include *server.out* to the pod's stdout. | `true` | +| `initialManagedServerReplicas` | Number of Managed Server to initially start for the domain. | `2` | +| `javaOptions` | Java options for starting the Administration Server and Managed Servers. A Java option can include references to one or more of the following pre-defined variables to obtain WebLogic domain information: `$(DOMAIN_NAME)`, `$(DOMAIN_HOME)`, `$(ADMIN_NAME)`, `$(ADMIN_PORT)`, and `$(SERVER_NAME)`. | `-Dweblogic.StdoutDebugEnabled=false` | +| `logHome` | The in-pod location for the domain log, server logs, server out, and Node Manager log files. `This field cannot be modified.` | `/u01/oracle/user_projects/logs/wcp-domain` | +| `managedServerNameBase` | Base string used to generate Managed Server names. | `wcpserver` | +| `managedServerPort` | Port number for each Managed Server. | `8888` | +| `managedServerSSLPort` | SSL port number for each Managed Server. | `8889` | +| `namespace` | Kubernetes namespace in which to create the domain. | `wcpns` | +| `persistentVolumeClaimName` | Name of the persistent volume claim created to host the domain home. If not specified, the value is derived from the `domainUID` as `-weblogic-sample-pvc`. | `wcp-domain-domain-pvc` | +| `productionModeEnabled` | Boolean indicating if production mode is enabled for the domain. | `true` | +| `serverStartPolicy` | Determines which WebLogic Server instances are to be started. Legal values are `NEVER`, `IF_NEEDED`, `ADMIN_ONLY`. | `IF_NEEDED` | +| `t3ChannelPort` | Port for the T3 channel of the *NetworkAccessPoint*. | `30012` | +| `t3PublicAddress` | Public address for the T3 channel. This should be set to the public address of the Kubernetes cluster. This would typically be a load balancer address.

For development environments only: In a single server (all-in-one) Kubernetes deployment, this may be set to the address of the master, or at the very least, it must be set to the address of one of the worker nodes. | If not provided, the script will attempt to set it to the IP address of the Kubernetes cluster. | +| `weblogicCredentialsSecretName` | Name of the Kubernetes secret for the Administration Server's user name and password. If not specified, then the value is derived from the `domainUID` as `-weblogic-credentials`. | wcpinfra-domain-credentials +| `weblogicImagePullSecretName` | Name of the Kubernetes secret for the Docker Store, used to pull the WebLogic Server image. | | +| `serverPodCpuRequest`, `serverPodMemoryRequest`, `serverPodCpuCLimit`, `serverPodMemoryLimit` | The maximum amount of compute resources allowed and minimum amount of compute resources required for each server pod. Please refer to the Kubernetes documentation on `Managing Compute Resources for Containers` for details. | Resource requests and resource limits are not specified. Refer to [WebCenter Portal Cluster Sizing Recommendations](../pre-requisites/#webcenter-portal-cluster-sizing-recommendations) for more details. | +| `rcuSchemaPrefix` | The schema prefix to use in the database, for example `WCP1`. You may wish to make this the same as the domainUID in order to simplify matching domain to their RCU schemas. | `WCP1` | +| `rcuDatabaseURL` | The database URL. | `dbhostname:dbport/servicename` | +| `rcuCredentialsSecret` | The Kubernetes secret containing the database credentials. | `wcpinfra-rcu-credentials` | +| `loadBalancerHostName` | Host name for the final url accessible outside K8S environment. | `abc.def.com` | +| `loadBalancerPortNumber` | Port for the final url accessible outside K8S environment. | `30305` | +| `loadBalancerProtocol` | Protocol for the final url accessible outside K8S environment. | `http` | +| `loadBalancerType` | Loadbalancer name. Example: Traefik or "" | `traefik` | +| `unicastPort` | Starting range of unicast port that application will use. | `50000` | + +You can form the names of the Kubernetes resources in the generated YAML files with the value of these properties +specified in the `create-domain-inputs.yaml` file: `adminServerName`, `clusterName` and `managedServerNameBase.` Characters that are invalid in a Kubernetes service name are converted to valid values in the +generated YAML files. For example, an uppercase letter is converted to a lowercase letter and an underscore ("_") is converted to a +hyphen ("-") . + +The sample demonstrates how to create a WebCenter Portal domain home and associated Kubernetes resources for a domain that has one cluster only. In addition, the sample provides users with the capability to supply their own scripts to create the domain home for other use cases. You can modify the generated domain YAML file to include more use cases. + +#### Create the WebCenter Portal Domain + +The syntax of the `create-domain.sh` script is as follows: + ``` + $ ./create-domain.sh \ + -i create-domain-inputs.yaml \ + -o / +``` + +The script performs the following functions: +* Creates a directory for the generated Kubernetes YAML files for this domain if it does not already exist. The path name is `//weblogic-domains/`.If the directory already exists, remove its content before using this script. +* Creates a Kubernetes job to start the WebCenter Portal Container utility and run offline WLST scripts that create the domain on the shared storage. +* Runs and waits for the job to finish. +* Creates a Kubernetes domain YAML file, `domain.yaml`, in the directory that is created above. + This YAML file can be used to create the Kubernetes resource using the `kubectl create -f` +or `kubectl apply -f` command: + + ``` + $ kubectl apply -f ..//weblogic-domains//domain.yaml + ``` + +* Creates a convenient utility script, `delete-domain-job.yaml`, to clean up the domain home created by the *create* script. + +1. Run the `create-domain.sh` sample script, pointing it at the `create-domain-inputs.yaml` inputs file and an output directory like below: + + ```bash + $ cd <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/ + $ sh create-domain.sh -i create-domain-inputs.yaml -o output + Input parameters being used + export version="create-weblogic-sample-domain-inputs-v1" + export sslEnabled="false" + export adminPort="7001" + export adminServerSSLPort="7002" + export adminServerName="AdminServer" + export domainUID="wcp-domain" + export domainHome="/u01/oracle/user_projects/domains/$domainUID" + export serverStartPolicy="IF_NEEDED" + export clusterName="wcp-cluster" + export configuredManagedServerCount="5" + export initialManagedServerReplicas="2" + export managedServerNameBase="wcpserver" + export managedServerPort="8888" + export managedServerSSLPort="8889" + export image="oracle/wcportal:12.2.1.4" + export imagePullPolicy="IfNotPresent" + export productionModeEnabled="true" + export weblogicCredentialsSecretName="wcpinfra-domain-credentials" + export includeServerOutInPodLog="true" + export logHome="/u01/oracle/user_projects/domains/logs/$domainUID" + export httpAccessLogInLogHome="true" + export t3ChannelPort="30012" + export exposeAdminT3Channel="false" + export adminNodePort="30701" + export exposeAdminNodePort="false" + export namespace="wcpns" + javaOptions=-Dweblogic.StdoutDebugEnabled=false + export persistentVolumeClaimName="wcp-domain-domain-pvc" + export domainPVMountPath="/u01/oracle/user_projects/domains" + export createDomainScriptsMountPath="/u01/weblogic" + export createDomainScriptName="create-domain-job.sh" + export createDomainFilesDir="wlst" + export rcuSchemaPrefix="WCP1" + export rcuDatabaseURL="oracle-db.wcpns.svc.cluster.local:1521/devpdb.k8s" + export rcuCredentialsSecret="wcpinfra-rcu-credentials" + export loadBalancerHostName="abc.def.com" + export loadBalancerPortNumber="30305" + export loadBalancerProtocol="http" + export loadBalancerType="traefik" + export unicastPort="50000" + + Generating output/weblogic-domains/wcp-domain/create-domain-job.yaml + Generating output/weblogic-domains/wcp-domain/delete-domain-job.yaml + Generating output/weblogic-domains/wcp-domain/domain.yaml + Checking to see if the secret wcpinfra-domain-credentials exists in namespace wcpns + configmap/wcp-domain-create-wcp-infra-sample-domain-job-cm created + Checking the configmap wcp-domain-create-wcp-infra-sample-domain-job-cm was created + configmap/wcp-domain-create-wcp-infra-sample-domain-job-cm labeled + Checking if object type job with name wcp-domain-create-wcp-infra-sample-domain-job exists + Deleting wcp-domain-create-wcp-infra-sample-domain-job using output/weblogic-domains/wcp-domain/create-domain-job.yaml + job.batch "wcp-domain-create-wcp-infra-sample-domain-job" deleted + $loadBalancerType is NOT empty + Creating the domain by creating the job output/weblogic-domains/wcp-domain/create-domain-job.yaml + job.batch/wcp-domain-create-wcp-infra-sample-domain-job created + Waiting for the job to complete... + status on iteration 1 of 20 + pod wcp-domain-create-wcp-infra-sample-domain-job-b5l6c status is Running + status on iteration 2 of 20 + pod wcp-domain-create-wcp-infra-sample-domain-job-b5l6c status is Running + status on iteration 3 of 20 + pod wcp-domain-create-wcp-infra-sample-domain-job-b5l6c status is Running + status on iteration 4 of 20 + pod wcp-domain-create-wcp-infra-sample-domain-job-b5l6c status is Running + status on iteration 5 of 20 + pod wcp-domain-create-wcp-infra-sample-domain-job-b5l6c status is Running + status on iteration 6 of 20 + pod wcp-domain-create-wcp-infra-sample-domain-job-b5l6c status is Running + status on iteration 7 of 20 + pod wcp-domain-create-wcp-infra-sample-domain-job-b5l6c status is Completed + + Domain wcp-domain was created and will be started by the WebLogic Kubernetes Operator + + The following files were generated: + output/weblogic-domains/wcp-domain/create-domain-inputs.yaml + output/weblogic-domains/wcp-domain/create-domain-job.yaml + output/weblogic-domains/wcp-domain/domain.yaml + + Completed + ``` + +1. To monitor the above domain creation logs: + + ```bash + $ kubectl get pods -n wcpns |grep wcp-domain-create + + wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 1/1 Running 0 6s + ``` + + ```bash + $ kubectl get pods -n wcpns | grep wcp-domain-create | awk '{print $1}' | xargs kubectl -n wcpns logs -f + ``` + + SAMPLE OUTPUT: + ``` + The domain will be created using the script /u01/weblogic/create-domain-script.sh + + Initializing WebLogic Scripting Tool (WLST) ... + + + Welcome to WebLogic Server Administration Scripting Shell + + Type help() for help on available commands + + ================================================================= + WebCenter Portal Weblogic Operator Domain Creation Script + 12.2.1.4.0 + ================================================================= + Creating Base Domain... + Creating Admin Server... + Creating cluster... + managed server name is wcpserver1 + managed server name is wcpserver2 + managed server name is wcpserver3 + managed server name is wcpserver4 + managed server name is wcpserver5 + ['wcpserver1', 'wcpserver2', 'wcpserver3', 'wcpserver4', 'wcpserver5'] + Managed servers created... + Creating Node Manager... + Will create Base domain at /u01/oracle/user_projects/domains/wcp-domain + Writing base domain... + Base domain created at /u01/oracle/user_projects/domains/wcp-domain + Extending Domain... + Extending domain at /u01/oracle/user_projects/domains/wcp-domain + Database oracle-db.wcpns.svc.cluster.local:1521/devpdb.k8s + ExposeAdminT3Channel false with 100.111.157.155:30012 + Applying JRF templates... + Applying WCPortal templates... + Extension Templates added... + WC_Portal Managed server deleted... + Configuring the Service Table DataSource... + fmwDatabase jdbc:oracle:thin:@oracle-db.wcpns.svc.cluster.local:1521/devpdb.k8s + Getting Database Defaults... + Targeting Server Groups... + Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcpserver1 + Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcpserver2 + Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcpserver3 + Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcpserver4 + Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcpserver5 + Targeting Cluster ... + Set CoherenceClusterSystemResource to defaultCoherenceCluster for cluster:wcp-cluster + Set WLS clusters as target of defaultCoherenceCluster:wcp-cluster + Preparing to update domain... + Jan 12, 2021 10:30:09 AM oracle.security.jps.az.internal.runtime.policy.AbstractPolicyImpl initializeReadStore + INFO: Property for read store in parallel: oracle.security.jps.az.runtime.readstore.threads = null + Domain updated successfully + Domain Creation is done... + Successfully Completed + + ``` + +#### Initialize the WebCenter Portal Domain + +To start the domain, apply the above `domain.yaml`: + +```bash +$ kubectl apply -f output/weblogic-domains/wcp-domain/domain.yaml +domain.weblogic.oracle/wcp-domain created +``` + +#### Verify the WebCenter Portal Domain +Verify that the domain and servers pods and services are created and in the READY state: + +Sample run below: +```bash +-bash-4.2$ kubectl get pods -n wcpns -w +NAME READY STATUS RESTARTS AGE +wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 0/1 Completed 0 15m +wcp-domain-adminserver 1/1 Running 0 8m9s +wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 0/1 Completed 0 3h6m +wcp-domain-wcp-server1 0/1 Running 0 6m5s +wcp-domain-wcp-server2 0/1 Running 0 6m4s +wcp-domain-wcp-server2 1/1 Running 0 6m18s +wcp-domain-wcp-server1 1/1 Running 0 6m54s + +``` + +```bash +-bash-4.2$ kubectl get all -n wcpns +NAME READY STATUS RESTARTS AGE +pod/wcp-domain-adminserver 1/1 Running 0 13m +pod/wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 0/1 Completed 0 3h12m +pod/wcp-domain-wcp-server1 1/1 Running 0 11m +pod/wcp-domain-wcp-server2 1/1 Running 0 11m + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/wcp-domain-adminserver ClusterIP None 7001/TCP 13m +service/wcp-domain-cluster-wcp-cluster ClusterIP 10.98.145.173 8888/TCP 11m +service/wcp-domain-wcp-server1 ClusterIP None 8888/TCP 11m +service/wcp-domain-wcp-server2 ClusterIP None 8888/TCP 11m + +NAME COMPLETIONS DURATION AGE +job.batch/wcp-domain-create-fmw-infra-sample-domain-job 1/1 16m 3h12m +``` + +To see the Admin and Managed Servers logs, you can check the pod logs: + +```bash +$ kubectl logs -f wcp-domain-adminserver -n wcpns +``` + +```bash +$ kubectl logs -f wcp-domain-wcp-server1 -n wcpns +``` + +#### Verify the Pods + +Use the following command to see the pods running the servers: + +``` +$ kubectl get pods -n NAMESPACE +``` + +Here is an example of the output of this command: + +``` +-bash-4.2$ kubectl get pods -n wcpns +NAME READY STATUS RESTARTS AGE +rcu 1/1 Running 1 14d +wcp-domain-adminserver 1/1 Running 0 16m +wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 0/1 Completed 0 3h14m +wcp-domain-wcp-server1 1/1 Running 0 14m +wcp-domain-wcp-server2 1/1 Running 0 14m +``` + +#### Verify the Services + +Use the following command to see the services for the domain: + +``` +$ kubectl get services -n NAMESPACE +``` + +Here is an example of the output of this command: +``` +-bash-4.2$ kubectl get services -n wcpns +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +wcp-domain-adminserver ClusterIP None 7001/TCP 17m +wcp-domain-cluster-wcp-cluster ClusterIP 10.98.145.173 8888/TCP 14m +wcp-domain-wcp-server1 ClusterIP None 8888/TCP 14m +wcp-domain-wcp-server2 ClusterIP None 8888/TCP 14m +``` +#### Managing WebCenter Portal + +To stop Managed Servers: + +```bash +$ kubectl patch domain wcp-domain -n wcpns --type='json' -p='[{"op": "replace", "path": "/spec/clusters/0/replicas", "value": 0 }]' +``` + +To start all configured Managed Servers: + +```bash +$ kubectl patch domain wcp-domain -n wcpns --type='json' -p='[{"op": "replace", "path": "/spec/clusters/0/replicas", "value": 3 }]' +``` + +```bash + -bash-4.2$ kubectl get pods -n wcpns -w + NAME READY STATUS RESTARTS AGE + wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 0/1 Completed 0 15m + wcp-domain-adminserver 1/1 Running 0 8m9s + wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 0/1 Completed 0 3h6m + wcp-domain-wcp-server1 0/1 Running 0 6m5s + wcp-domain-wcp-server2 0/1 Running 0 6m4s + wcp-domain-wcp-server2 1/1 Running 0 6m18s + wcp-domain-wcp-server1 1/1 Running 0 6m54s +``` + diff --git a/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md b/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md new file mode 100644 index 000000000..9577ed9aa --- /dev/null +++ b/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md @@ -0,0 +1,355 @@ ++++ +title = "Prepare your environment" +weight = 2 +pre = " " +description = "Prepare for creating the Oracle WebCenter Portal domain, This preparation includes but not limited to creating required secrets, persistent volume and volume claim, and database schema." ++++ + +Set up the environment, including setting up a Kubernetes cluster and the Weblogic Kubernetes Operator. + +1. [Install Helm](#install-helm) +1. [Set Up your Kubernetes Cluster](#set-up-your-kubernetes-cluster) +1. [Build Oracle WebCenter Portal Image](#build-oracle-webcenter-portal-image) +1. [Pull Other Dependent Images](#pull-other-dependent-images) +1. [Set Up the Code Repository to Deploy Oracle WebCenter Portal Domain](#set-up-the-code-repository-to-deploy-oracle-webcenter-portal-domain) +1. [Grant Roles and Clear Stale Resources](#grant-roles-and-clear-stale-resources) +1. [Install the WebLogic Kubernetes Operator](#install-the-weblogic-kubernetes-operator) +1. [Prepare the Environment for the WebCenter Portal Domain](#prepare-the-environment-for-the-webcenter-portal-domain) + + a. [Create a namespace for an Oracle WebCenter Portal domain](#create-a-namespace-for-an-oracle-webcenter-portal-domain) + + b. [Create a Kubernetes secret with domain credentials](#create-a-kubernetes-secret-with-domain-credentials) + + c. [Create a Kubernetes secret with the RCU credentials](#create-a-kubernetes-secret-with-the-rcu-credentials) + + d. [Create a persistent storage for an Oracle WebCenter Portal domain](#create-a-persistent-storage-for-an-oracle-webcenter-portal-domain) + + e. [Configure access to your database](#configure-access-to-your-database) + + f. [Run the Repository Creation Utility to set up your database schemas](#run-the-repository-creation-utility-to-set-up-your-database-schemas) + +### Install Helm + + The operator uses Helm to create and deploy the necessary resources and then run the operator in a Kubernetes cluster. For Helm installation and usage information, see [here](https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-operators/#install-helm). + + +### Set Up your Kubernetes Cluster + +If you need help in setting up a Kubernetes environment, check our [cheat sheet](https://oracle.github.io/weblogic-kubernetes-operator/userguide/overview/k8s-setup). + +After creating Kubernetes clusters, you can optionally: +* Create load balancers to direct traffic to backend domain +* Configure Kibana and Elasticsearch for your operator logs + +### Build Oracle WebCenter Portal Image + +Build Oracle WebCenter Portal 12.2.1.4 Image by following steps from this [document]({{< relref "/wcportal-domains/create-or-update-image/">}}). +### Pull Other Dependent Images + +Dependent images include WebLogic Kubernetes Operator, database, and Traefik. Pull these images and add them to your local registry: + +1. Pull these docker images and re-tag them as shown: + +To pull an image from the Oracle Container Registry, in a web browser, navigate to ```https://container-registry.oracle.com``` and log in using the Oracle Single Sign-On authentication service. If you do not already have SSO credentials, at the top of the page, click the Sign In link to create them. + +Use the web interface to accept the Oracle Standard Terms and Restrictions for the Oracle software images that you intend to deploy. Your acceptance of these terms are stored in a database that links the software images to your Oracle Single Sign-On login credentials. + +Then, pull these docker images: + +```bash +$ docker login https://container-registry.oracle.com (enter your Oracle email Id and password) +#This step is required once at every node to get access to the Oracle Container Registry. +``` + +WebLogic Kubernetes Operator image: +```bash +$ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.1.1 + +``` + +2. Copy all the built and pulled images to all the nodes in your cluster or add to a Docker registry that your cluster can access. + +NOTE: If you're not running Kubernetes on your development machine, you'll need to make the Docker image available to a registry visible to your Kubernetes cluster. + Upload your image to a machine running Docker and Kubernetes as follows: +```bash +# on your build machine +$ docker save Image_Name:Tag > Image_Name-Tag.tar +$ scp Image_Name-Tag.tar YOUR_USER@YOUR_SERVER:/some/path/Image_Name-Tag.tar + +# on the Kubernetes server +$ docker load < /some/path/Image_Name-Tag.tar +``` + +### Set Up the Code Repository to Deploy Oracle WebCenter Portal Domain + +Oracle WebCenter Portal domain deployment on Kubernetes leverages the WebLogic Kubernetes Operator infrastructure. For deploying the Oracle WebCenter Portal domain, you need to set up the deployment scripts as below: + +1. Create a working directory to set up the source code. + ```bash + $ export WORKDIR=$HOME/wcp_3.1.1 + $ mkdir + $ cd + ``` + +1. Download the supported version of WebLogic Kubernetes Operator source code archive file (`.zip`/`.tar.gz`) from the operator [relases page](https://github.com/oracle/weblogic-kubernetes-operator/releases). You can also download the supported operator version from [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/archive/v3.1.1.zip). + ```bash + $ git clone https://github.com/oracle/weblogic-kubernetes-operator.git --branch release/3.1.1 + ``` + +1. Download the WebCenter Portal Kubernetes deployment scripts from this [repository](https://github.com/oracle/fmw-kubernetes.git) and copy them in to WebLogic operator samples location. + + ```bash + $ git clone https://github.com/oracle/fmw-kubernetes.git --branch release/21.2.3 + + $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/create-wcp-domain ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ + $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/ingress-per-domain ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ + $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ + $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/imagetool-scripts ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ + $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/charts ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ + ``` + +You can now use the deployment scripts from `<$WORKDIR>/weblogic-kubernetes-operator` to set up the WebCenter Portal domain as described later in this document. + +Your home directory for running all the required scripts: + +```bash +$ cd <$WORKDIR>/weblogic-kubernetes-operator +``` + +### Grant Roles and Clear Stale Resources + +1. To confirm if there is already a WebLogic custom resource definition, execute the following command: + + ```bash + $ kubectl get crd + NAME CREATED AT + domains.weblogic.oracle 2020-03-14T12:10:21Z + ``` +1. Delete the WebLogic custom resource definition, if you find any, by executing the following command: + ```bash + $ kubectl delete crd domains.weblogic.oracle + customresourcedefinition.apiextensions.k8s.io "domains.weblogic.oracle" deleted + ``` + +### Install the WebLogic Kubernetes Operator + +1. Create a namespace for the WebLogic Kubernetes Operator: + + ```bash + $ kubectl create namespace operator-ns + namespace/operator-ns created + ``` + NOTE: In this procedure, the namespace is called “operator-ns”. You can use any name. + + You can use: + * domainUID/domainname as `wcp-domain` + * Domain namespace as `wcpns` + * Operator namespace as `operator-ns` + * traefik namespace as `traefik` + +1. Create a service account for the WebLogic Kubernetes Operator in the operator's namespace: + + ```bash + $ kubectl create serviceaccount -n operator-ns operator-sa + serviceaccount/operator-sa created + ``` + +1. To be able to set up the log-stash and Elasticsearch after creating the domain, set the value of the field `elkIntegrationEnabled` to `true` in the file `kubernetes/charts/weblogic-operator/values.yaml`. + +1. Use helm to install and start the WebLogic Kubernetes Operator from the downloaded repository: + + > Helm install weblogic-operator + + ```bash + $ helm install weblogic-kubernetes-operator kubernetes/charts/weblogic-operator --namespace operator-ns --set serviceAccount=operator-sa --set "domainNamespaces={}" --wait + + NAME: weblogic-kubernetes-operator + LAST DEPLOYED: Wed Jan 6 01:47:33 2021 + NAMESPACE: operator-ns + STATUS: deployed + REVISION: 1 + TEST SUITE: None + ``` + +1. To verify that the operator's pod is running, list the pods in the operator's namespace. You should see one for the WebLogic Kubernetes Operator: + + ```bash + $ kubectl get pods -n operator-ns + NAME READY STATUS RESTARTS AGE + weblogic-operator-67df5fddc5-tlc4b 2/2 Running 0 3m15s + ``` + +1. Then, check by viewing the Operator pod's log as shown in the following sample log snippet: + + ```bash + $ kubectl logs -n operator-ns -c weblogic-operator deployments/weblogic-operator + Launching Oracle WebLogic Server Kubernetes Operator... + Importing keystore /operator/internal-identity/temp/weblogic-operator.jks to /operator/internal-identity/temp/weblogic-operator.p12... + Entry for alias weblogic-operator-alias successfully imported. + Import command completed: 1 entries successfully imported, 0 entries failed or cancelled + + Warning: + The -srcstorepass option is specified multiple times. All except the last one will be ignored. + MAC verified OK + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 4249 0 2394 100 1855 6884 5334 --:--:-- --:--:-- --:--:-- 6899 + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 5558 0 3028 100 2530 22704 18970 --:--:-- --:--:-- --:--:-- 22766 + OpenJDK 64-Bit Server VM warning: Option MaxRAMFraction was deprecated in version 10.0 and will likely be removed in a future release. + VM settings: + Max. Heap Size (Estimated): 14.08G + Using VM: OpenJDK 64-Bit Server VM + + {"timestamp":"03-14-2020T06:49:53.438+0000","thread":1,"fiber":"","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.TuningParametersImpl","method":"update","timeInMillis":1584168593438,"message":"Reloading tuning parameters from Operator's config map","exception":"","code":"","headers":{},"body":""} + {"timestamp":"03-14-2020T06:49:53.944+0000","thread":1,"fiber":"","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.Main","method":"main","timeInMillis":1584168593944,"message":"Oracle WebLogic Server Kubernetes Operator, version: 3.0.4, implementation: master.4d4fe0a, build time: 2019-11-15T21:19:56-0500","exception":"","code":"","headers":{},"body":""} + {"timestamp":"03-14-2020T06:49:53.972+0000","thread":11,"fiber":"","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.Main","method":"begin","timeInMillis":1584168593972,"message":"Operator namespace is: operator-ns","exception":"","code":"","headers":{},"body":""} + {"timestamp":"03-14-2020T06:49:54.009+0000","thread":11,"fiber":"","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.Main","method":"begin","timeInMillis":1584168594009,"message":"Operator target namespaces are: operator-ns","exception":"","code":"","headers":{},"body":""} + {"timestamp":"03-14-2020T06:49:54.013+0000","thread":11,"fiber":"","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.Main","method":"begin","timeInMillis":1584168594013,"message":"Operator service account is: operator-sa","exception":"","code":"","headers":{},"body":""} {"timestamp":"03-14-2020T06:49:54.031+0000","thread":11,"fiber":"","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.helpers.HealthCheckHelper","method":"performK8sVersionCheck","timeInMillis":1584168594031,"message":"Verifying Kubernetes minimum version","exception":"","code":"","headers":{},"body":""} {"timestamp":"03-14-2020T06:49:54.286+0000","thread":11,"fiber":"","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.helpers.ClientPool","method":"getApiClient","timeInMillis":1584168594286,"message":"The Kuberenetes Master URL is set to https://10.96.0.1:443","exception":"","code":"","headers":{},"body":""} {"timestamp":"03-14-2020T06:49:54.673+0000","thread":11,"fiber":"","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.helpers.HealthCheckHelper","method":"createAndValidateKubernetesVersion","timeInMillis":1584168594673,"message":"Kubernetes version is: v1.13.7","exception":"","code":"","headers":{},"body":""} {"timestamp":"03-14-2020T06:49:55.259+0000","thread":12,"fiber":"engine-operator-thread-2-fiber-1","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.helpers.CrdHelper$CrdContext$CreateResponseStep","method":"onSuccess","timeInMillis":1584168595259,"message":"Create Custom Resource Definition: oracle.kubernetes.operator.calls.CallResponse@470b40c","exception":"","code":"","headers":{},"body":""} {"timestamp":"03-14-2020T06:49:55.356+0000","thread":16,"fiber":"fiber-1-child-2","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.helpers.HealthCheckHelper","method":"performSecurityChecks","timeInMillis":1584168595356,"message":"Verifying that operator service account can access required operations on required resources in namespace operator-ns","exception":"","code":"","headers":{},"body":""} {"timestamp":"03-14-2020T06:49:55.598+0000","thread":18,"fiber":"fiber-1-child-2","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.helpers.ConfigMapHelper$ScriptConfigMapContext$CreateResponseStep","method":"onSuccess","timeInMillis":1584168595598,"message":"Creating domain config map, operator-ns, for namespace: {1}.","exception":"","code":"","headers":{},"body":""} {"timestamp":"03-14-2020T06:49:55.937+0000","thread":21,"fiber":"fiber-1","domainUID":"","level":"WARNING","class":"oracle.kubernetes.operator.utils.Certificates","method":"getCertificate","timeInMillis":1584168595937,"message":"Can't read certificate at /operator/external-identity/externalOperatorCert","exception":"\njava.nio.file.NoSuchFileException: /operator/external-identity/externalOperatorCert\n\tat java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)\n\tat java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)\n\tat java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)\n\tat java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:215)\n\tat java.base/java.nio.file.Files.newByteChannel(Files.java:370)\n\tat java.base/java.nio.file.Files.newByteChannel(Files.java:421)\n\tat java.base/java.nio.file.Files.readAllBytes(Files.java:3205)\n\tat oracle.kubernetes.operator.utils.Certificates.getCertificate(Certificates.java:48)\n\tat oracle.kubernetes.operator.utils.Certificates.getOperatorExternalCertificateData(Certificates.java:39)\n\tat oracle.kubernetes.operator.rest.RestConfigImpl.getOperatorExternalCertificateData(RestConfigImpl.java:52)\n\tat oracle.kubernetes.operator.rest.RestServer.isExternalSslConfigured(RestServer.java:383)\n\tat oracle.kubernetes.operator.rest.RestServer.start(RestServer.java:199)\n\tat oracle.kubernetes.operator.Main.startRestServer(Main.java:353)\n\tat oracle.kubernetes.operator.Main.completeBegin(Main.java:198)\n\tat oracle.kubernetes.operator.Main$NullCompletionCallback.onCompletion(Main.java:701)\n\tat oracle.kubernetes.operator.work.Fiber.completionCheck(Fiber.java:475)\n\tat oracle.kubernetes.operator.work.Fiber.run(Fiber.java:448)\n\tat oracle.kubernetes.operator.work.ThreadLocalContainerResolver.lambda$wrapExecutor$0(ThreadLocalContainerResolver.java:87)\n\tat java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)\n\tat java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)\n\tat java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)\n\tat java.base/java.lang.Thread.run(Thread.java:834)\n","code":"","headers":{},"body":""} + {"timestamp":"03-14-2020T06:49:55.967+0000","thread":21,"fiber":"fiber-1","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.rest.RestServer","method":"start","timeInMillis":1584168595967,"message":"Did not start the external ssl REST server because external ssl has not been configured.","exception":"","code":"","headers":{},"body":""} + {"timestamp":"03-14-2020T06:49:57.910+0000","thread":21,"fiber":"fiber-1","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.rest.RestServer","method":"start","timeInMillis":1584168597910,"message":"Started the internal ssl REST server on https://0.0.0.0:8082/operator","exception":"","code":"","headers":{},"body":""} {"timestamp":"03-14-2020T06:49:57.913+0000","thread":21,"fiber":"fiber-1","domainUID":"","level":"INFO","class":"oracle.kubernetes.operator.Main","method":"markReadyAndStartLivenessThread","timeInMillis":1584168597913,"message":"Starting Operator Liveness Thread","exception":"","code":"","headers":{},"body":""} + + ``` + +### Prepare the Environment for the WebCenter Portal Domain + +#### Create a namespace for an Oracle WebCenter Portal domain + Unless you want to use the default namespace, create a Kubernetes namespace that can host one or more domains: +```bash +$ kubectl create namespace wcpns + namespace/wcpns created +``` + + + To manage domain in this namespace, configure the operator using helm: + + +>Helm upgrade weblogic-operator +```bash + $ helm upgrade --reuse-values --set "domainNamespaces={wcpns}" \ + --wait weblogic-kubernetes-operator kubernetes/charts/weblogic-operator --namespace operator-ns + + NAME: weblogic-kubernetes-operator + LAST DEPLOYED: Wed Jan 6 01:52:58 2021 + NAMESPACE: operator-ns + STATUS: deployed + REVISION: 2 +``` + +#### Create a Kubernetes secret with domain credentials + + + Using the create-weblogic-credentials script, create a Kubernetes secret that contains the user name and password for the domain in the same Kubernetes namespace as the domain: + +```bash +$ sh kubernetes/samples/scripts/create-weblogic-domain-credentials/create-weblogic-credentials.sh \ + -u weblogic -p welcome1 -n wcpns \ + -d wcp-domain -s wcpinfra-domain-credentials + + secret/wcpinfra-domain-credentials created + secret/wcpinfra-domain-credentials labeled + The secret wcpinfra-domain-credentials has been successfully created in the wcpns namespace. + ``` + Where: + + * weblogic is the weblogic username + * welcome1 is the weblogic password + * wcp-domain is the domain name + * wcpns is the domain namespace + * wcpinfra-domain-credentials is the secret name + + Note: You can inspect the credentials as follows: + ```bash + $ kubectl get secret wcpinfra-domain-credentials -o yaml -n wcpns +``` + #### Create a Kubernetes secret with the RCU credentials + Create a Kubernetes secret for the Repository Configuration Utility (user name and password) using the `create-rcu-credentials.sh` script in the same Kubernetes namespace as the domain: + + ```bash + $ sh kubernetes/samples/scripts/create-rcu-credentials/create-rcu-credentials.sh \ + -u WCP1 -p welcome1 -a sys -q Oradoc_db1 -n wcpns \ + -d wcp-domain -s wcpinfra-rcu-credentials + + secret/wcpinfra-rcu-credentials created + secret/wcpinfra-rcu-credentials labeled + The secret wcpinfra-rcu-credentials has been successfully created in the wcpns namespace. + ``` + Where: + + * WCP1 is the schema user + * welcome1 is the schema password + * Oradoc_db1 is the database SYS users password + * wcp-domain is the domain name + * wcpns is the domain namespace + * wcpinfra-rcu-credentials is the secret name + + Note: You can inspect the credentials as follows: + + ```bash + $ kubectl get secret wcpinfra-rcu-credentials -o yaml -n wcpns + ``` + +#### Create a persistent storage for an Oracle WebCenter Portal domain + Create a Kubernetes PV and PVC (Persistent Volume and Persistent Volume Claim): + + In the Kubernetes namespace you created, create the PV and PVC for the domain by running the [create-pv-pvc.sh](https://oracle.github.io/weblogic-kubernetes-operator/samples/simple/storage/) script. Follow the instructions for using the script to create a dedicated PV and PVC for the Oracle WebCenter Portal domain. + + * Review the configuration parameters for PV creation [here](https://oracle.github.io/weblogic-kubernetes-operator/samples/simple/storage/#configuration-parameters). Based on your requirements, update the values in the `create-pv-pvc-inputs.yaml` file located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-weblogic-domain-pv-pvc/`. Sample configuration parameter values for an Oracle WebCenter Portal domain are: + * `baseName`: domain + * `domainUID`: wcp-domain + * `namespace`: wcpns + * `weblogicDomainStorageType`: HOST_PATH + * `weblogicDomainStoragePath`: /scratch/kubevolume + + * Ensure that the path for the `weblogicDomainStoragePath` property exists (create one if it doesn't exist), that it has full access permissions, and that the folder is empty. + * Run the `create-pv-pvc.sh` script: + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-weblogic-domain-pv-pvc + $ ./create-pv-pvc.sh -i create-pv-pvc-inputs.yaml -o output + Input parameters being used + export version="create-weblogic-sample-domain-pv-pvc-inputs-v1" + export baseName="domain" + export domainUID="wcp-domain" + export namespace="wcpns" + export weblogicDomainStorageType="HOST_PATH" + export weblogicDomainStoragePath="/scratch/kubevolume" + export weblogicDomainStorageReclaimPolicy="Retain" + export weblogicDomainStorageSize="10Gi" + + Generating output/pv-pvcs/wcp-domain-domain-pv.yaml + Generating output/pv-pvcs/wcp-domain-domain-pvc.yaml + The following files were generated: + output/pv-pvcs/wcp-domain-domain-pv.yaml + output/pv-pvcs/wcp-domain-domain-pvc.yaml + ``` + * The `create-pv-pvc.sh` script creates a subdirectory `pv-pvcs` under the given `/path/to/output-directory` directory and creates two YAML configuration files for PV and PVC. Apply these two YAML files to create the PV and PVC Kubernetes resources using the `kubectl create -f` command: + ```bash + $ kubectl create -f output/pv-pvcs/wcp-domain-domain-pv.yaml + $ kubectl create -f output/pv-pvcs/wcp-domain-domain-pvc.yaml + ``` +#### Configure access to your database + +Oracle WebCenter Portal domain requires a database which is configured with the necessary schemas. The Repository Creation Utility (RCU) allows you to create +those schemas. You must set up the database before you create your domain. + +For production deployments, you must set up and use a standalone (non-container) database running outside of Kubernetes. + +Before creating a domain, you need to set up the necessary schemas in your database. +#### Run the Repository Creation Utility to set up your database schemas + Run a container to create Repository Creation Utility. + + ```bash + $ kubectl run rcu --generator=run-pod/v1 --image oracle/wcportal:12.2.1.4 -n wcpns -- sleep infinity + #check the status of rcu pod + $ kubectl get pods -n wcpns + #make sure rcu pod status is running before executing this + $ kubectl exec -n wcpns -ti rcu /bin/bash + export CONNECTION_STRING=databasehostname:/ + export RCUPREFIX=WCP1 + echo -e "\n" > /tmp/pwd.txt + /u01/oracle/oracle_common/bin/rcu -silent -dropRepository -databaseType ORACLE -connectString $CONNECTION_STRING -dbUser sys -dbRole sysdba -selectDependentsForComponents true -schemaPrefix $RCUPREFIX -component OPSS -component IAU_VIEWER -component WEBCENTER -component MDS -component IAU_APPEND -component STB -component IAU -component WLS -f < /tmp/pwd.txt + /u01/oracle/oracle_common/bin/rcu -silent -createRepository -databaseType ORACLE -connectString $CONNECTION_STRING -dbUser sys -dbRole sysdba -useSamePasswordForAllSchemaUsers true -selectDependentsForComponents true -schemaPrefix $RCUPREFIX -component OPSS -component IAU_VIEWER -component WEBCENTER -component MDS -component IAU_APPEND -component STB -component IAU -component WLS -tablespace USERS -tempTablespace TEMP -f < /tmp/pwd.txt + #exit from the container + exit + ``` \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/installguide/prerequisites/_index.md b/docs-source/content/wcportal-domains/installguide/prerequisites/_index.md new file mode 100644 index 000000000..c20f0f5bb --- /dev/null +++ b/docs-source/content/wcportal-domains/installguide/prerequisites/_index.md @@ -0,0 +1,50 @@ ++++ +title = "Requirements and limitations" +weight = 1 +pre = " " +description = "Understand the system requirements and limitations for deploying and running Oracle WebCenter Portal with the WebLogic Kubernetes operator." ++++ + +#### Contents + +* [Introduction](#introduction) +* [System Requirements](#system-requirements) +* [Limitations](#limitations) + +#### Introduction + +This document describes the special considerations for deploying and running a WebCenter Portal domain with the WebLogic Kubernetes Operator. +Other than those considerations listed here, the WebCenter Portal domain works in the same way as Fusion Middleware Infrastructure and WebLogic Server domains do. + +In this release, WebCenter Portal domain is based on the `domain on a persistent volume` [model](https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/choosing-a-model/) where a WebCenter Portal domain is located in a persistent volume (PV). + +#### System Requirements +* Kubernetes 1.14.8+, 1.15.7+, 1.16.0+, 1.17.0+, and 1.18.0+ (check with `kubectl version`). +* Flannel networking v0.9.1-amd64 or later (check with `docker images | grep flannel`). +* Docker 18.9.1 or 19.03.1 (check with `docker version`). +* Helm 3.1.3+ (check with `helm version`). +* WebLogic Kubernetes operator 3.1.1 (see [the operator releases](https://github.com/oracle/weblogic-kubernetes-operator/releases/tag/v3.1.1) page). +* Oracle WebCenter Portal 12.2.1.4.0 image. +* These proxy setups are used for pulling the required binaries and source code from the respective repositories: + * export NO_PROXY="localhost,127.0.0.0/8,$(hostname -i),.your-company.com,/var/run/docker.sock" + * export no_proxy="localhost,127.0.0.0/8,$(hostname -i),.your-company.com,/var/run/docker.sock" + * export http_proxy=http://www-proxy-your-company.com:80 + * export https_proxy=http://www-proxy-your-company.com:80 + * export HTTP_PROXY=http://www-proxy-your-company.com:80 + * export HTTPS_PROXY=http://www-proxy-your-company.com:80 + +NOTE: Add your host IP by using `hostname -i` and `nslookup` IP addresses to the no_proxy, NO_PROXY list above. + +#### Limitations + +Compared to running a WebLogic Server domain in Kubernetes using the operator, the +following limitations currently exist for a WebCenter Portal domain: + +* `Domain in image` model is not supported in this version of the operator. +* Only configured clusters are supported. Dynamic clusters are not supported on WebCenter Portal domains. Note that you can still use all of the scaling features. You just need to define the maximum size of your cluster at the time when you create a domain. +* At present, WebCenter Portal doesn't run on non-Linux containers. +* Deploying and running a WebCenter Portal domain is supported only in the operator versions 3.1.1 and later. +* The [WebLogic Logging Exporter](https://github.com/oracle/weblogic-logging-exporter) + currently supports WebLogic Server logs only. Other logs are not sent to Elasticsearch. Note, however, that you can use a sidecar with a log handling tool like Fluentd to get logs. +* The [WebLogic Monitoring Exporter](https://github.com/oracle/weblogic-monitoring-exporter) + currently supports the WebLogic MBean trees only. Support for JRF MBeans has not been added yet. \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/_index.md new file mode 100644 index 000000000..839cea0fb --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/_index.md @@ -0,0 +1,13 @@ ++++ +title = "Administration Guide" +date = 2019-04-18T07:32:31-05:00 +weight = 4 +pre = "3. " +description = "Describes how to use some common utility tools and configurations to administer WebCenter Portal domain." ++++ + + +Administer Oracle WebCenter Portal domain in Kubernetes. + +{{% children style="h4" description="true" %}} + diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/_index.md new file mode 100644 index 000000000..4cdf23135 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/_index.md @@ -0,0 +1,13 @@ ++++ +title = "Set up a load balancer" +date = 2019-02-22T15:44:42-05:00 +draft = false +weight = 1 +pre = " " +description = "Configure different load balancers for the Oracle WebCenter Portal domain." ++++ + +The WebLogic Kubernetes Operator supports ingress-based load balancers such as Traefik, NGINX (kubernetes/ingress-nginx) and Voyager. It also supports the Apache webtier load balancer. + + +{{% children style="h4" description="true" %}} diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/apachewebtier.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/apachewebtier.md new file mode 100644 index 000000000..f7948a7b7 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/apachewebtier.md @@ -0,0 +1,195 @@ ++++ +title = "Apache webtier" +date = 2019-02-22T15:44:42-05:00 +draft = false +weight = 4 +pre = "d. " +description = "Configure the Apache webtier load balancer for an Oracle WebCenter Portal domain." ++++ + +To load balance Oracle WebCenter Portal domain clusters, you can install Apache webtier and configure it for non-SSL and SSL termination access of the application URL. +Follow these steps to set up Apache webtier as a load balancer for an Oracle WebCenter Portal domain in a Kubernetes cluster: + + 1. [Build the Apache webtier image](#build-the-apache-webtier-image) + 1. [Create the Apache plugin configuration file](#create-the-apache-plugin-configuration-file) + 1. [Prepare the certificate and private key](#prepare-the-certificate-and-private-key) + 1. [Install the Apache webtier Helm chart](#install-the-apache-webtier-helm-chart) + 1. [Verify domain application URL access](#verify-domain-application-url-access) + 1. [Uninstall Apache webtier](#uninstall-apache-webtier) + +#### Build the Apache webtier image + +To build the Apache webtier Docker image, refer to the [sample](https://github.com/oracle/docker-images/tree/master/OracleWebLogic/samples/12213-webtier-apache). + +#### Create the Apache plugin configuration file + +1. The configuration file named `custom_mod_wl_apache.conf` should have all the URL routing rules for the Oracle WebCenter Portal applications deployed in the domain that needs to be accessible externally. Update this file with values based on your environment. The file content is similar to below. + + +{{%expand "Click here to see the sample content of the configuration file custom_mod_wl_apache.conf for wcp-domain domain" %}} +```bash +$ cat <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/charts/apache-samples/custom-sample/custom_mod_wl_apache.conf + +#Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. +# +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + + +WebLogicHost +WebLogicPort 7001 + + +# Directive for weblogic admin Console deployed on Weblogic Admin Server + +SetHandler weblogic-handler +WebLogicHost wcp-domain-adminserver +WebLogicPort 7001 + + + +SetHandler weblogic-handler +WebLogicHost wcp-domain-adminserver +WebLogicPort 7001 + + + +WLSRequest On +WebLogicCluster wcp-domain-cluster-wcp-cluster:8888 +PathTrim /weblogic1 + + + +WLSRequest On +WebLogicCluster wcp-domain-cluster-wcp-cluster:8888 +PathTrim /weblogic1 + + + +WLSRequest On +WebLogicCluster wcp-domain-cluster-wcp-cluster:8888 +PathTrim /weblogic1 + + + +WLSRequest On +WebLogicCluster wcp-domain-cluster-wcp-cluster:8888 +PathTrim /weblogic1 + +``` +{{% /expand %}} + +1. Update `persistentVolumeClaimName` in `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/charts/apache-samples/custom-sample/input.yaml`with Persistence Volume which contains your own custom_mod_wl_apache.conf file. Use the PV/PVC created at the time of preparing environment, Copy the custom_mod_wl_apache.conf file to existing PersistantVolume. +#### Prepare the certificate and private key + +1. (For the SSL termination configuration only) Run the following commands to generate your own certificate and private key using `openssl`. + + ```bash + $ cd <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/charts/apache-samples/custom-sample + $ export VIRTUAL_HOST_NAME=WEBLOGIC_HOST + $ export SSL_CERT_FILE=WEBLOGIC_HOST.crt + $ export SSL_CERT_KEY_FILE=WEBLOGIC_HOST.key + $ sh certgen.sh + ``` + > NOTE: Replace WEBLOGIC_HOST with the name of the host on which Apache webtier is to be installed. + + {{%expand "Click here to see the output of the certifcate generation" %}} + ```bash + $ls + certgen.sh custom_mod_wl_apache.conf custom_mod_wl_apache.conf_orig input.yaml README.md + $ sh certgen.sh + Generating certs for WEBLOGIC_HOST + Generating a 2048 bit RSA private key + ........................+++ + .......................................................................+++ + unable to write 'random state' + writing new private key to 'apache-sample.key' + ----- + $ ls + certgen.sh custom_mod_wl_apache.conf_orig WEBLOGIC_HOST.info + config.txt input.yaml WEBLOGIC_HOST.key + custom_mod_wl_apache.conf WEBLOGIC_HOST.crt README.md + ``` + {{% /expand %}} +1. Prepare input values for the Apache webtier Helm chart. + + Run the following commands to prepare the input value file for the Apache webtier Helm chart. + + ```bash + $ base64 -i ${SSL_CERT_FILE} | tr -d '\n' + $ base64 -i ${SSL_CERT_KEY_FILE} | tr -d '\n' + $ touch input.yaml + ``` + + Update `virtualHostName` with the value of the `WEBLOGIC_HOST` in file `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/charts/apache-samples/custom-sample/input.yaml` + + {{%expand "Click here to see the snapshot of the sample input.yaml file " %}} + ```bash + $ cat apache-samples/custom-sample/input.yaml + # Use this to provide your own Apache webtier configuration as needed; simply define this + # path and put your own custom_mod_wl_apache.conf file under this path. + persistentVolumeClaimName: wcp-domain-domain-pvc + + # The VirtualHostName of the Apache HTTP server. It is used to enable custom SSL configuration. + virtualHostName: + ``` + {{% /expand %}} +#### Install the Apache webtier Helm chart + +1. Install the Apache webtier Helm chart to the domain `wcpns` namespace with the specified input parameters: + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts + $ kubectl create namespace apache-webtier + $ helm install apache-webtier --values apache-samples/custom-sample/input.yaml --namespace wcpns apache-webtier --set image=oracle/apache:12.2.1.3 + ``` + +1. Check the status of the Apache webtier: + + ```bash + $ kubectl get all -n wcpns | grep apache + ``` + + Sample output of the status of the apache webtier: + ```bash + pod/apache-webtier-apache-webtier-65f69dc6bc-zg5pj 1/1 Running 0 22h + service/apache-webtier-apache-webtier NodePort 10.108.29.98 80:30305/TCP,4433:30443/TCP 22h + deployment.apps/apache-webtier-apache-webtier 1/1 1 1 22h + replicaset.apps/apache-webtier-apache-webtier-65f69dc6bc 1 1 1 22h + ``` + +#### Verify domain application URL access + +Once the Apache webtier load balancer is up, verify that the domain applications are accessible through the load balancer port `30305/30443`. The application URLs for domain of type `wcp` are: + +> Note: Port `30305` is the LOADBALANCER-Non-SSLPORT and Port `30443` is LOADBALANCER-SSLPORT. + +##### Non-SSL configuration + + ```bash + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/console + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/em + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenter + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenterhelp + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rest + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rsscrawl + + ``` + +##### SSL configuration + + ```bash + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenter + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/console + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/em + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rest + + ``` + +#### Uninstall Apache webtier + + ```bash + $ helm delete apache-webtier -n wcpns + ``` diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md new file mode 100644 index 000000000..c7e3c10e6 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md @@ -0,0 +1,403 @@ ++++ +title = "NGINX" +date = 2019-02-22T15:44:42-05:00 +draft = false +weight = 2 +pre = "b. " +description = "Configure the ingress-based NGINX load balancer for an Oracle WebCenter Portal domain." ++++ + +To load balance Oracle WebCenter Portal domain clusters, you can install the ingress-based *NGINX* load balancer and configure NGINX for both SSL and non-SSL access of the application URL. +Follow these steps to set up NGINX as a load balancer for an Oracle WebCenter Portal domain in a Kubernetes cluster: + + See the official [installation document](https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx#prerequisites) for prerequisites. + +* [ Non-SSL and SSL termination](#non-ssl-and-ssl-termination) + 1. [Install the NGINX load balancer](#install-the-nginx-load-balancer) + 2. [Configure NGINX to manage ingresses](#configure-nginx-to-manage-ingresses) + 3. [Verify non-SSL and SSL termination access](#verify-non-ssl-and-ssl-termination-access) + +* [ End-to-end SSL configuration](#end-to-end-ssl-configuration) + 1. [Install the NGINX load balancer for End-to-end SSL](#install-the-nginx-load-balancer-for-end-to-end-ssl) + 2. [Deploy tls to access the services](#deploy-tls-to-access-services) + 3. [Verify end-to-end SSL access](#verify-end-to-end-ssl-access) + +### Non-SSL and SSL termination + To get repository information, enter the following Helm commands: + + ```bash + $ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx + $ helm repo update + ``` + +#### Install the NGINX load balancer + +1. Deploy the `ingress-nginx` controller by using Helm on the domain namespace: + + ```bash + $ helm install nginx-ingress ingress-nginx/ingress-nginx -n wcpns \ + --set controller.service.type=NodePort \ + --set controller.admissionWebhooks.enabled=false + ``` + {{%expand "Click here to see the sample output." %}} + NAME: nginx-ingress + LAST DEPLOYED: Tue Jan 12 21:13:54 2021 + NAMESPACE: wcpns + STATUS: deployed + REVISION: 1 + TEST SUITE: None + NOTES: + The ingress-nginx controller has been installed. + Get the application URL by running these commands: + export HTTP_NODE_PORT=30305 + export HTTPS_NODE_PORT=$(kubectl --namespace wcpns get services -o jsonpath="{.spec.ports[1].nodePort}" nginx-ingress-ingress-nginx-controller) + export NODE_IP=$(kubectl --namespace wcpns get nodes -o jsonpath="{.items[0].status.addresses[1].address}") + + echo "Visit http://$NODE_IP:$HTTP_NODE_PORT to access your application via HTTP." + echo "Visit https://$NODE_IP:$HTTPS_NODE_PORT to access your application via HTTPS." + + An example Ingress that makes use of the controller: + + apiVersion: networking.k8s.io/v1beta1 + kind: Ingress + metadata: + annotations: + kubernetes.io/ingress.class: nginx + name: example + namespace: foo + spec: + rules: + - host: www.example.com + http: + paths: + - backend: + serviceName: exampleService + servicePort: 80 + path: / + # This section is only required if TLS is to be enabled for the Ingress + tls: + - hosts: + - www.example.com + secretName: example-tls + + If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided: + + apiVersion: v1 + kind: Secret + metadata: + name: example-tls + namespace: foo + data: + tls.crt: + tls.key: + type: kubernetes.io/tls + + {{% /expand %}} + +1. Check the status of the deployed ingress controller: + ```bash + $ kubectl --namespace wcpns get services | grep ingress-nginx-controller + ``` + Sample output: + ```bash + nginx-ingress-ingress-nginx-controller NodePort 10.101.123.106 80:30305/TCP,443:31856/TCP 2m12s + ``` + +#### Configure NGINX to manage ingresses + +1. Create an ingress for the domain in the domain namespace by using the sample Helm chart. Here path-based routing is used for ingress. Sample values for default configuration are shown in the file `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/values.yaml`. By default, `type` is `TRAEFIK`, `tls` is `Non-SSL`. You can override these values by passing values through the command line or edit them in the sample `values.yaml` file. If needed, you can update the ingress YAML file to define more path rules (in section `spec.rules.host.http.paths`) based on the domain application URLs that need to be accessed. Update the template YAML file for the NGINX load balancer located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/templates/nginx-ingress.yaml` + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm install wcp-nginx-ingress kubernetes/samples/charts/ingress-per-domain \ + --namespace wcpns \ + --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --set "nginx.hostname=$(hostname -f)" \ + --set type=NGINX + ``` + + Sample output: + ```bash + NAME: wcp-nginx-ingress + LAST DEPLOYED: Fri Jul 24 09:34:03 2020 + NAMESPACE: wcpns + STATUS: deployed + REVISION: 1 + TEST SUITE: None + ``` +1. For secured access (SSL) to the Oracle WebCenter Portal application, create a certificate and generate a Kubernetes secret: + + ```bash + $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" + $ kubectl -n wcpns create secret tls domain1-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + ``` +1. Install `ingress-per-domain` using Helm for SSL configuration: + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm install wcp-nginx-ingress kubernetes/samples/charts/ingress-per-domain \ + --namespace wcpns \ + --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --set "nginx.hostname=$(hostname -f)" \ + --set type=NGINX --set tls=SSL + ``` +1. For non-SSL access to the Oracle WebCenter Portal application, get the details of the services by the ingress: + + ```bash + $ kubectl describe ingress wcp-domain-ingress -n wcpns + ``` + {{%expand "Click here to see the sample output of the services supported by the above deployed ingress." %}} + Name: wcp-domain-ingress + Namespace: wcpns + Address: 10.101.123.106 + Default backend: default-http-backend:80 () + Rules: + Host Path Backends + ---- ---- -------- + * + /webcenter wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /console wcp-domain-adminserver:7001 (10.244.0.51:7001) + /rsscrawl wcp-domain-cluster-wcp-cluster:8888 (10.244.0.53:8888) + /rest wcp-domain-cluster-wcp-cluster:8888 (10.244.0.53:8888) + /webcenterhelp wcp-domain-cluster-wcp-cluster:8888 (10.244.0.53:8888) + /em wcp-domain-adminserver:7001 (10.244.0.51:7001) + Annotations: meta.helm.sh/release-name: wcp-nginx-ingress + meta.helm.sh/release-namespace: wcpns + nginx.com/sticky-cookie-services: serviceName=wcp-domain-cluster-wcp-cluster srv_id expires=1h path=/; + nginx.ingress.kubernetes.io/proxy-connect-timeout: 1800 + nginx.ingress.kubernetes.io/proxy-read-timeout: 1800 + nginx.ingress.kubernetes.io/proxy-send-timeout: 1800 + Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Sync 48m (x2 over 48m) nginx-ingress-controller Scheduled for sync + + {{% /expand %}} + 1. For SSL access to the Oracle WebCenter Portal application, get the details of the services by the above deployed ingress: + + ```bash + $ kubectl describe ingress wcp-domain-ingress -n wcpns + ``` + {{%expand "Click here to see the sample output of the services supported by the above deployed ingress." %}} + Name: wcp-domain-ingress + Namespace: wcpns + Address: 10.106.220.140 + Default backend: default-http-backend:80 () + TLS: + domain1-tls-cert terminates mydomain.com + Rules: + Host Path Backends + ---- ---- -------- + * + /webcenter wcp-domain-cluster-wcp-cluster:8888 (10.244.0.43:8888,10.244.0.44:8888) + /console wcp-domain-adminserver:7001 (10.244.0.42:7001) + /rsscrawl wcp-domain-cluster-wcp-cluster:8888 (10.244.0.43:8888,10.244.0.44:8888) + /webcenterhelp wcp-domain-cluster-wcp-cluster:8888 (10.244.0.43:8888,10.244.0.44:8888) + /rest wcp-domain-cluster-wcp-cluster:8888 (10.244.0.43:8888,10.244.0.44:8888) + /em wcp-domain-adminserver:7001 (10.244.0.42:7001) + Annotations: kubernetes.io/ingress.class: nginx + meta.helm.sh/release-name: wcp-nginx-ingress + meta.helm.sh/release-namespace: wcpns + nginx.ingress.kubernetes.io/affinity: cookie + nginx.ingress.kubernetes.io/affinity-mode: persistent + nginx.ingress.kubernetes.io/configuration-snippet: + more_set_input_headers "X-Forwarded-Proto: https"; + more_set_input_headers "WL-Proxy-SSL: true"; + nginx.ingress.kubernetes.io/ingress.allow-http: false + nginx.ingress.kubernetes.io/proxy-connect-timeout: 1800 + nginx.ingress.kubernetes.io/proxy-read-timeout: 1800 + nginx.ingress.kubernetes.io/proxy-send-timeout: 1800 + nginx.ingress.kubernetes.io/session-cookie-expires: 172800 + nginx.ingress.kubernetes.io/session-cookie-max-age: 172800 + nginx.ingress.kubernetes.io/session-cookie-name: stickyid + nginx.ingress.kubernetes.io/ssl-redirect: false + Events: + {{% /expand %}} +#### Verify non-SSL and SSL termination access +Verify that the Oracle WebCenter Portal domain application URLs are accessible through the ngnix NodePort `LOADBALANCER-NODEPORT` `30305`: + +```bash + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/console + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/em + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/webcenter + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/rsscrawl + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/rest + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/webcenterhelp + +``` + + + +#### Uninstall the ingress + +Uninstall and delete the `ingress-nginx` deployment: + +```bash + $ helm delete wcp-nginx-ingress -n wcpns + $ helm delete nginx-ingress -n wcpns +``` + + +### End-to-end SSL configuration + +#### Install the NGINX load balancer for End-to-end SSL + +1. For secured access (SSL) to the Oracle WebCenter Portal application, create a certificate and generate secrets: + + ```bash + $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=domain1.org" + $ kubectl -n wcpns create secret tls domain1-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + ``` + > Note: The value of `CN` is the host on which this ingress is to be deployed. + +1. Deploy the ingress-nginx controller by using Helm on the domain namespace: + ```bash + $ helm install nginx-ingress -n wcpns \ + --set controller.extraArgs.default-ssl-certificate=wcpns/domain1-tls-cert \ + --set controller.service.type=NodePort \ + --set controller.admissionWebhooks.enabled=false \ + --set controller.extraArgs.enable-ssl-passthrough=true \ + ingress-nginx/ingress-nginx + ``` + {{%expand "Click here to see the sample output." %}} + ```bash + NAME: nginx-ingress + LAST DEPLOYED: Tue Sep 15 08:40:47 2020 + NAMESPACE: wcpns + STATUS: deployed + REVISION: 1 + TEST SUITE: None + NOTES: + The ingress-nginx controller has been installed. + Get the application URL by running these commands: + export HTTP_NODE_PORT=$(kubectl --namespace wcpns get services -o jsonpath="{.spec.ports[0].nodePort}" nginx-ingress-ingress-nginx-controller) + export HTTPS_NODE_PORT=$(kubectl --namespace wcpns get services -o jsonpath="{.spec.ports[1].nodePort}" nginx-ingress-ingress-nginx-controller) + export NODE_IP=$(kubectl --namespace wcpns get nodes -o jsonpath="{.items[0].status.addresses[1].address}") + + echo "Visit http://$NODE_IP:$HTTP_NODE_PORT to access your application via HTTP." + echo "Visit https://$NODE_IP:$HTTPS_NODE_PORT to access your application via HTTPS." + + An example Ingress that makes use of the controller: + + apiVersion: networking.k8s.io/v1beta1 + kind: Ingress + metadata: + annotations: + kubernetes.io/ingress.class: nginx + name: example + namespace: foo + spec: + rules: + - host: www.example.com + http: + paths: + - backend: + serviceName: exampleService + servicePort: 80 + path: / + # This section is only required if TLS is to be enabled for the Ingress + tls: + - hosts: + - www.example.com + secretName: example-tls + + If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided: + apiVersion: v1 + kind: Secret + metadata: + name: example-tls + namespace: foo + data: + tls.crt: + tls.key: + type: kubernetes.io/tls + ``` + {{% /expand %}} + +1. Check the status of the deployed ingress controller: + ```bash + $ kubectl --namespace wcpns get services | grep ingress-nginx-controller + ``` + Sample output: + + ```bash + nginx-ingress-ingress-nginx-controller NodePort 10.96.177.215 80:32748/TCP,443:31940/TCP 23s + ``` + +#### Deploy tls to access services + +1. Deploy tls to securely access the services. Only one application can be configured with `ssl-passthrough`. A sample tls file for NGINX is shown below for the service `wcp-domain-cluster-wcp-cluster` and port `8889`. All the applications running on port `8889` can be securely accessed through this ingress. + +1. For each backend service, create different ingresses, as NGINX does not support multiple paths or rules with annotation `ssl-passthrough`. For example, for `wcp-domain-adminserver` and `wcp-domain-cluster-wcp-cluster,` different ingresses must be created. + +1. As `ssl-passthrough` in NGINX works on the clusterIP of the backing service instead of individual endpoints, you must expose `wcp-domain-cluster-wcp-cluster` created by the operator with clusterIP. + + For example: + a. Get the name of wcp-domain cluster service: + ```bash + $ kubectl get svc -n wcpns | grep wcp-domain-cluster-wcp-cluster + ``` + Sample output: + ```bash + wcp-domain-cluster-wcp-cluster ClusterIP 10.102.128.124 8888/TCP,8889/TCP 62m + ``` +1. Deploy the secured ingress: + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls + $ kubectl create -f nginx-tls.yaml + ``` + > Note: The default `nginx-tls.yaml` contains the backend for WebCenter Portal service with domainUID `wcp-domain`. You need to create similar tls configuration YAML files separately for each backend service. + + {{%expand "Click here to check the content of the file nginx-tls.yaml" %}} + + apiVersion: extensions/v1beta1 + kind: Ingress + metadata: + name: wcpns-ingress + namespace: wcpns + annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + spec: + tls: + - hosts: + - domain1.org + secretName: domain1-tls-cert + rules: + - host: domain1.org + http: + paths: + - path: + backend: + serviceName: wcp-domain-cluster-wcp-cluster + servicePort: 8889 + + + + {{% /expand %}} + + > Note: Host is the server on which this ingress is deployed. + + +1. Check the services supported by the ingress: + ```bash + $ kubectl describe ingress wcpns-ingress -n wcpns + ``` +#### Verify end-to-end SSL access + +Verify that the Oracle WebCenter Portal domain application URLs are accessible through the `LOADBALANCER-SSLPORT` `30233`: + ```bash + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenter + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rest + + ``` + +#### Uninstall ingress-nginx tls + + ```bash + $ cd weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls + $ kubectl delete -f nginx-tls.yaml + $ helm delete nginx-ingress -n wcpns + ``` diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md new file mode 100644 index 000000000..e3e2857a9 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md @@ -0,0 +1,496 @@ ++++ +title = "Traefik" +date = 2019-02-22T15:44:42-05:00 +draft = false +weight = 1 +pre = "a. " +description = "Configure the ingress-based Traefik load balancer for an Oracle WebCenter Portal domain." ++++ + +To load balance Oracle WebCenter Portal domain clusters, you can install the ingress-based *Traefik* load balancer (version 2.2.1 or later for production deployments) and configure it for non-SSL and SSL-based access of the application URL.Follow these steps to set up Traefik as a load balancer for an Oracle WebCenter Portal domain in a Kubernetes cluster: + +* [ Non-SSL and SSL termination](#non-ssl-and-ssl-termination) + 1. [Install the Traefik (ingress-based) load balancer](#install-the-traefik-ingress-based-load-balancer) + 2. [Configure Traefik to manage ingresses](#configure-traefik-to-manage-ingresses) + 3. [Create an Ingress for the domain](#create-an-ingress-for-the-domain) + 4. [Verify domain application URL access](#verify-domain-application-url-access) + 5. [Uninstall the Traefik ingress](#uninstall-the-traefik-ingress) + +* [ End-to-end SSL configuration](#end-to-end-ssl-configuration) + 1. [Install the Traefik load balancer for End-to-end SSL](#install-the-traefik-load-balancer-for-end-to-end-ssl) + 2. [Configure Traefik to manage domain](#configure-traefik-to-manage-the-domain) + 3. [Create IngressRouteTCP](#create-ingressroutetcp) + 4. [Verify end-to-end SSL access](#verify-end-to-end-ssl-access) + 5. [Uninstall Traefik](#uninstall-traefik) + +### Non-SSL and SSL termination + +#### Install the Traefik (ingress-based) load balancer + +1. Use Helm to install the Traefik (ingress-based) load balancer. +You can use the following `values.yaml` sample file and set kubernetes.namespaces as required. + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ kubectl create namespace traefik + $ helm repo add traefik https://containous.github.io/traefik-helm-chart + ``` + Sample output: + ```bash + "traefik" has been added to your repositories + ``` +2. Install Traefik: + + ```bash + $ helm install traefik traefik/traefik \ + --namespace traefik \ + --values kubernetes/samples/scripts/charts/traefik/values.yaml \ + --set "kubernetes.namespaces={traefik}" \ + --set "service.type=NodePort" --wait + ``` + {{%expand "Click here to see the sample output." %}} + ```bash + LAST DEPLOYED: Sun Sep 13 21:32:00 2020 + NAMESPACE: traefik + STATUS: deployed + REVISION: 1 + TEST SUITE: None + ``` + {{% /expand %}} + + A sample `values.yaml` for deployment of Traefik 2.2.x looks like this: + ```yaml + image: + name: traefik + tag: 2.2.8 + pullPolicy: IfNotPresent + ingressRoute: + dashboard: + enabled: true + annotations: {} + labels: {} + providers: + kubernetesCRD: + enabled: true + kubernetesIngress: + enabled: true + ports: + traefik: + port: 9000 + expose: true + exposedPort: 9000 + protocol: TCP + web: + port: 8000 + expose: true + exposedPort: 30305 + nodePort: 30305 + protocol: TCP + websecure: + port: 8443 + expose: true + exposedPort: 30443 + protocol: TCP + nodePort: 30443 + ``` + +1. Verify the Traefik status and find the port number of the SSL and non-SSL services: + ```bash + $ kubectl get all -n traefik + ``` + {{%expand "Click here to see the sample output." %}} + ```bash +NAME READY STATUS RESTARTS AGE +pod/traefik-f9cf58697-29dlx 1/1 Running 0 35s + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/traefik NodePort 10.100.113.37 9000:30070/TCP,30305:30305/TCP,30443:30443/TCP 35s + +NAME READY UP-TO-DATE AVAILABLE AGE +deployment.apps/traefik 1/1 1 1 36s + +NAME DESIRED CURRENT READY AGE +replicaset.apps/traefik-f9cf58697 1 1 1 36s + +``` + {{% /expand %}} + +4. Access the Traefik dashboard through the URL `http://$(hostname -f):30070`, with the HTTP host `traefik.example.com`: + + ```bash + $ curl -H "host: $(hostname -f)" http://$(hostname -f):30070/dashboard/ + ``` + > Note: Make sure that you specify a fully qualified node name for `$(hostname -f)` + +#### Configure Traefik to manage ingresses + +Configure Traefik to manage ingresses created in this namespace. In the following sample, `traefik` is the Traefik namespace and `wcpns` is the namespace of the domain: +```bash +$ helm upgrade traefik traefik/traefik \ +--reuse-values \ +--namespace traefik \ +--set "kubernetes.namespaces={traefik,wcpns}" \ +--wait +``` + {{%expand "Click here to see the sample output." %}} +```bash +Release "traefik" has been upgraded. Happy Helming! +NAME: traefik +LAST DEPLOYED: Tue Jan 12 04:33:15 2021 +NAMESPACE: traefik +STATUS: deployed +REVISION: 2 +TEST SUITE: None +``` + {{% /expand %}} + +#### Create an ingress for the domain + +Create an ingress for the domain in the domain namespace by using the sample Helm chart. Here path-based routing is used for ingress. +Sample values for default configuration are shown in the file `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/values.yaml`. +By default, `type` is `TRAEFIK` , `tls` is `Non-SSL`. You can override these values by passing values through the command line or edit them in the sample `values.yaml` file based on the type of configuration (non-SSL or SSL). +If needed, you can update the ingress YAML file to define more path rules (in section `spec.rules.host.http.paths`) based on the domain application URLs that need to be accessed. The template YAML file for the Traefik (ingress-based) load balancer is located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/templates/traefik-ingress.yaml` + +1. Install `ingress-per-domain` using Helm for non-SSL configuration: + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm install wcp-traefik-ingress \ + kubernetes/samples/charts/ingress-per-domain \ + --namespace wcpns \ + --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --set "traefik.hostname=$(hostname -f)" + ``` + Sample output: + ```bash + NAME: wcp-traefik-ingress + LAST DEPLOYED: Mon Jul 20 11:44:13 2020 + NAMESPACE: wcpns + STATUS: deployed + REVISION: 1 + TEST SUITE: None + ``` + +1. For secured access (SSL) to the Oracle WebCenter Portal application, create a certificate and generate a Kubernetes secret: + + ```bash + $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" + $ kubectl -n wcpns create secret tls wcpinfra-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + ``` + > Note: The value of `CN` is the host on which this ingress is to be deployed. + +1. Create a Traefik Middleware custom resource + + In case of SSL termination, Traefik must pass a custom header `WL-Proxy-SSL:true` to the WebLogic Server endpoints. Create the Middleware using the following command: + ```bash + $ cat <-@kubernetescrd`. + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm install wcp-traefik-ingress \ + kubernetes/samples/charts/ingress-per-domain \ + --namespace wcpns \ + --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --set "traefik.hostname=$(hostname -f)" \ + --set tls=SSL + ``` + Sample output: + ```bash + NAME: wcp-traefik-ingress + LAST DEPLOYED: Mon Jul 20 11:44:13 2020 + NAMESPACE: wcpns + STATUS: deployed + REVISION: 1 + TEST SUITE: None + + ``` +1. For non-SSL access to the Oracle WebCenter Portal application, get the details of the services by the ingress: + + ```bash + $ kubectl describe ingress wcp-domain-traefik -n wcpns + ``` + {{%expand "Click here to see all services supported by the above deployed ingress." %}} + + ```bash + Name: wcp-domain-traefik + Namespace: wcpns + Address: + Default backend: default-http-backend:80 () + Rules: + Host Path Backends + ---- ---- -------- + www.example.com + /webcenter wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /console wcp-domain-adminserver:7001 (10.244.0.51:7001) + /rsscrawl wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /rest wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /webcenterhelp wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /em wcp-domain-adminserver:7001 (10.244.0.51:7001) + Annotations: kubernetes.io/ingress.class: traefik + meta.helm.sh/release-name: wcp-traefik-ingress + meta.helm.sh/release-namespace: wcpns + Events: + ``` + {{% /expand %}} + +1. For SSL access to the Oracle WebCenter Portal application, get the details of the services by the above deployed ingress: + + ```bash + $ kubectl describe ingress wcp-domain-traefik -n wcpns + ``` + {{%expand "Click here to see all services supported by the above deployed ingress." %}} + ``` +Name: wcp-domain-traefik +Namespace: wcpns +Address: +Default backend: default-http-backend:80 () +TLS: + wcpinfra-tls-cert terminates www.example.com +Rules: + Host Path Backends + ---- ---- -------- + www.example.com + /webcenter wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /console wcp-domain-adminserver:7001 (10.244.0.51:7001) + /rsscrawl wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /rest wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /webcenterhelp wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) + /em wcp-domain-adminserver:7001 (10.244.0.51:7001) +Annotations: kubernetes.io/ingress.class: traefik + meta.helm.sh/release-name: wcp-traefik-ingress + meta.helm.sh/release-namespace: wcpns + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.middlewares: wcpns-wls-proxy-ssl@kubernetescrd + traefik.ingress.kubernetes.io/router.tls: true +Events: +``` + {{% /expand %}} + +1. To confirm that the load balancer noticed the new ingress and is successfully routing to the domain server pods, you can send a request to the URL for the WebLogic ReadyApp framework, which should return an HTTP 200 status code, as follows: + ```bash + $ curl -v http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER_PORT}/weblogic/ready + * Trying 149.87.129.203... + > GET http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER_PORT}/weblogic/ready HTTP/1.1 + > User-Agent: curl/7.29.0 + > Accept: */* + > Proxy-Connection: Keep-Alive + > host: $(hostname -f) + > + < HTTP/1.1 200 OK + < Date: Sat, 14 Mar 2020 08:35:03 GMT + < Vary: Accept-Encoding + < Content-Length: 0 + < Proxy-Connection: Keep-Alive + < + * Connection #0 to host localhost left intact + ``` +#### Verify domain application URL access + +##### For non-SSL configuration + +After setting up the Traefik (ingress-based) load balancer, verify that the domain application URLs are accessible through the non-SSL load balancer port `30305` for HTTP access. The sample URLs for Oracle WebCenter Portal domain are: + +```bash + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenter + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/console + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/em + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rsscrawl + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rest + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenterhelp + +``` + +##### For SSL configuration + +After setting up the Traefik (ingress-based) load balancer, verify that the domain applications are accessible through the SSL load balancer port `30443` for HTTPS access. The sample URLs for Oracle WebCenter Portal domain are: + +```bash + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenter + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/console + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/em + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/rest + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp + +``` + +#### Uninstall the Traefik ingress + +Uninstall and delete the ingress deployment: + +```bash +$ helm delete wcp-traefik-ingress -n wcpns +``` + + +### End-to-end SSL configuration + +#### Install the Traefik load balancer for end-to-end SSL + +1. Use Helm to install the Traefik (ingress-based) load balancer. You can use the `values.yaml` sample file and set kubernetes.namespaces as required. + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ kubectl create namespace traefik + $ helm repo add traefik https://containous.github.io/traefik-helm-chart + ``` + Sample output: + ```bash + "traefik" has been added to your repositories + ``` +1. Install Traefik: + + ```bash + $ helm install traefik traefik/traefik \ + --namespace traefik \ + --values kubernetes/samples/scripts/charts/traefik/values.yaml \ + --set "kubernetes.namespaces={traefik}" \ + --set "service.type=NodePort" --wait + ``` + {{%expand "Click here to see the sample output." %}} + ```bash + LAST DEPLOYED: Sun Sep 13 21:32:00 2020 + NAMESPACE: traefik + STATUS: deployed + REVISION: 1 + TEST SUITE: None + ``` + {{% /expand %}} + +1. Verify the Traefik operator status and find the port number of the SSL and non-SSL services: + ```bash + $ kubectl get all -n traefik + ``` + {{%expand "Click here to see the sample output." %}} + ```bash + + NAME READY STATUS RESTARTS AGE + pod/traefik-845f5d6dbb-swb96 1/1 Running 0 32s + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + service/traefik LoadBalancer 10.99.52.249 9000:31288/TCP,30305:30305/TCP,30443:30443/TCP 32s + + NAME READY UP-TO-DATE AVAILABLE AGE + deployment.apps/traefik 1/1 1 1 33s + + NAME DESIRED CURRENT READY AGE + replicaset.apps/traefik-845f5d6dbb 1 1 1 33s + + ``` + {{% /expand %}} + +1. Access the Traefik dashboard through the URL `http://$(hostname -f):31288`, with the HTTP host `traefik.example.com`: + + ```bash + $ curl -H "host: $(hostname -f)" http://$(hostname -f):31288/dashboard/ + ``` + > Note: Make sure that you specify a fully qualified node name for `$(hostname -f)`. + +#### Configure Traefik to manage the domain + +Configure Traefik to manage the domain application service created in this namespace. In the following sample, `traefik` is the Traefik namespace and `wcpns` is the namespace of the domain: +```bash +$ helm upgrade traefik traefik/traefik --namespace traefik --reuse-values \ +--set "kubernetes.namespaces={traefik,wcpns}" +``` + {{%expand "Click here to see the sample output." %}} + Release "traefik" has been upgraded. Happy Helming! + NAME: traefik + LAST DEPLOYED: Sun Sep 13 21:32:12 2020 + NAMESPACE: traefik + STATUS: deployed + REVISION: 2 + TEST SUITE: None + + {{% /expand %}} + +#### Create IngressRouteTCP + +1. To enable SSL passthrough in Traefik, you can configure a TCP router. A sample YAML for `IngressRouteTCP` is available at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls/traefik-tls.yaml`. The following should be updated in `traefik-tls.yaml`: + * The service name and the SSL port should be updated in the `services`. + * The load balancer host name should be updated in the `HostSNI` rule. + + Sample `traefik-tls.yaml`: + ```yaml + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRouteTCP + metadata: + name: wcp-domain-cluster-routetcp + namespace: wcpns + spec: + entryPoints: + - websecure + routes: + - match: HostSNI(`${LOADBALANCER_HOSTNAME}`) + services: + - name: wcp-domain-cluster-wcp-cluster + port: 8888 + weight: 3 + TerminationDelay: 400 + tls: + passthrough: true + ``` +1. Create the IngressRouteTCP: + ```bash + $ kubectl apply -f traefik-tls.yaml + ``` + +#### Verify end-to-end SSL access + +Verify the access to application URLs exposed through the configured service. The configured WCP cluster service enables you to access the following WCP domain URLs: + ```bash + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenter + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/rest + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp + + ``` + +#### Uninstall Traefik + + ```bash + $ helm delete traefik -n traefik + $ cd weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls + $ kubectl delete -f traefik-tls.yaml + ``` diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/voyager.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/voyager.md new file mode 100644 index 000000000..42d33aed0 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/voyager.md @@ -0,0 +1,526 @@ ++++ +title = "Voyager" +date = 2019-02-22T15:44:42-05:00 +draft = false +weight = 3 +pre = "c. " +description = "Configure the ingress-based Voyager load balancer for an Oracle WebCenter Portal domain." ++++ + +*Voyager/HAProxy* is a popular ingress-based load balancer for production environments. +You can install and configure *Voyager/HAProxy* to load balance Oracle WebCenter Portal domain clusters and configure it for non-SSL, SSL termination, and end-to-end SSL access of the application URL. +Follow these steps to set up Voyager as a load balancer for an Oracle WebCenter Portal domain in a Kubernetes cluster: + +* [ Non-SSL and SSL termination](#non-ssl-and-ssl-termination) + + 1. [Install the Voyager load balancer](#install-the-voyager-load-balancer) + 2. [Configure Voyager to manage ingresses](#configure-voyager-to-manage-ingresses) + 3. [Verify non-SSL and SSL access](#verify-non-ssl-and-ssl-access) + +* [ End-to-end SSL configuration](#end-to-end-ssl-configuration) + 1. [Install Voyager load balancer for end-to-end SSL](#install-voyager-load-balancer-for-end-to-end-ssl) + 2. [Deploy tls to access the services](#deploy-tls-to-access-services) + 3. [Verify end-to-end SSL access](#verify-end-to-end-ssl-access) + +#### Non-SSL and SSL termination + +##### Install the Voyager load balancer + +1. Add the AppsCode chart repository: + + ```bash + $ helm repo add appscode https://charts.appscode.com/stable/ + $ helm repo update + ``` +1. Verify that the chart repository has been added: + + ```bash + $ helm search repo appscode/voyager + ``` + > **NOTE**: After updating the Helm repository, the Voyager version listed may be newer that the one shown here. Check with the Voyager site for the latest supported versions. + +1. Install the Voyager operator: + + > **NOTE**: The Voyager version you install must match the version found with the helm search. + + ```bash + $ kubectl create namespace voyager + $ helm install voyager-operator appscode/voyager --version 10.0.0 \ + --namespace voyager \ + --set cloudProvider=baremetal \ + --set apiserver.enableValidatingWebhook=false + ``` + + Wait until the Voyager operator is running. + +1. Check the status of the Voyager operator: + ```bash + $ kubectl get all -n voyager + ``` + {{%expand "Click here to see the sample output." %}} + + NAME READY STATUS RESTARTS AGE + pod/voyager-operator-b84f95f8f-4szhl 1/1 Running 0 43h + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + service/voyager-operator ClusterIP 10.107.201.155 443/TCP,56791/TCP 43h + + NAME READY UP-TO-DATE AVAILABLE AGE + deployment.apps/voyager-operator 1/1 1 1 43h + + NAME DESIRED CURRENT READY AGE + replicaset.apps/voyager-operator-b84f95f8f 1 1 1 43h + + {{% /expand %}} + + See the official [installation document](https://github.com/oracle/weblogic-kubernetes-operator/blob/master/kubernetes/samples/charts/voyager/README.md#a-step-by-step-guide-to-install-the-voyager-operator) for more details. + +1. Update the Voyager operator. + Once the Voyager operator is installed, and it is running, upgrade it using the `helm upgrade` command. In this command, `voyager` is the Voyager namespace and `wcpns` is the namespace of the domain. + + ```bash + $ helm upgrade voyager-operator appscode/voyager --namespace voyager + ``` + {{%expand "Click here to see the sample output." %}} + Release "voyager-operator" has been upgraded. Happy Helming! + NAME: voyager-operator + LAST DEPLOYED: Mon Sep 28 11:53:43 2020 + NAMESPACE: voyager + STATUS: deployed + REVISION: 2 + TEST SUITE: None + NOTES: + Set cloudProvider for installing Voyager + + To verify that Voyager has started, run: + + kubectl get deployment --namespace voyager -l "app.kubernetes.io/name=voyager,app.kubernetes.io/instance=voyager-operator" + + {{% /expand %}} + +##### Configure Voyager to manage ingresses + +1. Create an ingress for the domain in the domain namespace by using the sample Helm chart. Here path-based routing is used for ingress. Sample values for default configuration are shown in the file `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/values.yaml`. By default, `type` is `TRAEFIK` , `tls` is `Non-SSL`. You can override these values by passing your values through the command line or edit the existing values in the sample `values.yaml` file. + + If needed, you can update the ingress yaml file to define more path rules (in the `spec.rules.host.http.paths` section) based on the domain application URLs that need to be accessed. You need to update the template yaml file for the Voyager (ingress-based) load balancer located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/templates/voyager-ingress.yaml` + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm install wcp-voyager-ingress kubernetes/samples/charts/ingress-per-domain \ + --namespace wcpns \ + --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --set type=VOYAGER + ``` + {{%expand "Click here to check the output of the ingress per domain " %}} + ```bash + NAME: wcp-voyager-ingress + LAST DEPLOYED: Mon Jul 20 08:20:27 2020 + NAMESPACE: wcpns + STATUS: deployed + REVISION: 1 + TEST SUITE: None + ``` + {{% /expand %}} +1. For secured access (SSL) to the Oracle WebCenter Portal application, create a certificate and generate secrets: + ```bash + $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" + $ kubectl -n wcpns create secret tls wcpinfra-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + ``` + > Note: The value of `CN` is the host on which this ingress is to be deployed. + +1. Deploy `ingress-per-domain` using Helm for SSL configuration. + + If needed, you can update the ingress yaml file to define more path rules (in the `spec.rules.host.http.paths section`) based on the domain application URLs that need to be accessed. You need to update the template yaml file for the Voyager (ingress-based) load balancer located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/templates/voyager-ingress.yaml` + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ helm install wcp-voyager-ingress kubernetes/samples/charts/ingress-per-domain \ + --namespace wcpns \ + --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --set type=VOYAGER \ + --set tls=SSL + ``` + {{%expand "Click here to see the sample output of the above Commnad." %}} + ```bash + NAME: wcp-voyager-ingress + LAST DEPLOYED: Mon Jul 20 08:20:27 2020 + NAMESPACE: wcpns + STATUS: deployed + REVISION: 1 + TEST SUITE: None + ``` + {{% /expand %}} + +1. For non-SSL access to the Oracle WebCenter Portal application, get the details of the services deployed by the above ingress: + + ```bash + $ kubectl describe ingress.voyager.appscode.com/wcp-domain-voyager -n wcpns + ``` + {{%expand "Click here to see the sample output of the services supported by the above deployed ingress." %}} + Sample output: + ```bash + Name: wcp-domain-voyager + Namespace: wcpns + Labels: app.kubernetes.io/managed-by=Helm + Annotations: ingress.appscode.com/affinity: cookie + ingress.appscode.com/stats: true + ingress.appscode.com/type: NodePort + meta.helm.sh/release-name: wcp-voyager-ingress + meta.helm.sh/release-namespace: wcpns + API Version: voyager.appscode.com/v1beta1 + Kind: Ingress + Metadata: + Creation Timestamp: 2021-01-13T08:19:16Z + Generation: 1 + Managed Fields: + API Version: voyager.appscode.com/v1beta1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:ingress.appscode.com/affinity: + f:ingress.appscode.com/stats: + f:ingress.appscode.com/type: + f:meta.helm.sh/release-name: + f:meta.helm.sh/release-namespace: + f:labels: + .: + f:app.kubernetes.io/managed-by: + f:spec: + .: + f:rules: + Manager: Go-http-client + Operation: Update + Time: 2021-01-13T08:19:16Z + Resource Version: 340890 + Self Link: /apis/voyager.appscode.com/v1beta1/namespaces/wcpns/ingresses/wcp-domain-voyager + UID: a06315c2-23ad-4916-a972-cd3555494eb8 + Spec: + Rules: + Host: * + Http: + Node Port: 30305 + Paths: + Backend: + Service Name: wcp-domain-cluster-wcp-cluster + Service Port: 8888 + Path: /webcenter + Backend: + Service Name: wcp-domain-adminserver + Service Port: 7001 + Path: /console + Backend: + Service Name: wcp-domain-cluster-wcp-cluster + Service Port: 8888 + Path: /rsscrawl + Backend: + Service Name: wcp-domain-adminserver + Service Port: 7001 + Path: /em + Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal ServiceReconcileSuccessful 62s voyager-operator Successfully created NodePort Service voyager-wcp-domain-voyager + Normal ConfigMapReconcileSuccessful 62s voyager-operator Successfully created ConfigMap voyager-wcp-domain-voyager + Normal RBACSuccessful 62s voyager-operator Successfully created ServiceAccount voyager-wcp-domain-voyager + Normal RBACSuccessful 62s voyager-operator Successfully created Role voyager-wcp-domain-voyager + Normal RBACSuccessful 62s voyager-operator Successfully created RoleBinding voyager-wcp-domain-voyager + Normal DeploymentReconcileSuccessful 62s voyager-operator Successfully created HAProxy Deployment voyager-wcp-domain-voyager + Normal StatsServiceReconcileSuccessful 62s voyager-operator Successfully created stats Service voyager-wcp-domain-voyager-stats + + ``` + {{% /expand %}} + +1. For SSL access to the Oracle WebCenter Portal application, get the details of the services by the above deployed ingress: + + ```bash + $ kubectl describe ingress.voyager.appscode.com/wcp-domain-voyager -n wcpns + ``` + {{%expand "Click here to see all the services configured by the above deployed ingress." %}} + + ```bash + Name: wcp-domain-voyager + Namespace: wcpns + Labels: app.kubernetes.io/managed-by=Helm + Annotations: ingress.appscode.com/affinity: cookie + ingress.appscode.com/stats: true + ingress.appscode.com/type: NodePort + meta.helm.sh/release-name: wcp-domain-ingress + meta.helm.sh/release-namespace: wcpns + API Version: voyager.appscode.com/v1beta1 + Kind: Ingress + Metadata: + Creation Timestamp: 2021-01-15T05:40:20Z + Generation: 1 + Managed Fields: + API Version: voyager.appscode.com/v1beta1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:ingress.appscode.com/affinity: + f:ingress.appscode.com/stats: + f:ingress.appscode.com/type: + f:meta.helm.sh/release-name: + f:meta.helm.sh/release-namespace: + f:labels: + .: + f:app.kubernetes.io/managed-by: + f:spec: + .: + f:frontendRules: + f:rules: + f:tls: + Manager: Go-http-client + Operation: Update + Time: 2021-01-15T05:40:20Z + Resource Version: 704682 + Self Link: /apis/voyager.appscode.com/v1beta1/namespaces/wcpns/ingresses/wcp-domain-voyager + UID: 1e83c6a6-336f-4e29-b38a-023e00ca5cd5 + Spec: + Frontend Rules: + Port: 443 + Rules: + http-request set-header WL-Proxy-SSL true + Rules: + Host: * + Http: + Node Port: 30305 + Paths: + Backend: + Service Name: wcp-domain-cluster-wcp-cluster + Service Port: 8888 + Path: /webcenter + Backend: + Service Name: wcp-domain-adminserver + Service Port: 7001 + Path: /console + Backend: + Service Name: wcp-domain-cluster-wcp-cluster + Service Port: 8888 + Path: /rsscrawl + Backend: + Service Name: wcp-domain-cluster-wcp-cluster + Service Port: 8888 + Path: /rest + Backend: + Service Name: wcp-domain-cluster-wcp-cluster + Service Port: 8888 + Path: /webcenterhelp + Backend: + Service Name: wcp-domain-adminserver + Service Port: 7001 + Path: /em + Tls: + Hosts: + * + Secret Name: domain1-tls-cert + Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal ServiceReconcileSuccessful 54s voyager-operator Successfully created NodePort Service voyager-wcp-domain-voyager + Normal ConfigMapReconcileSuccessful 54s voyager-operator Successfully created ConfigMap voyager-wcp-domain-voyager + Normal RBACSuccessful 54s voyager-operator Successfully created ServiceAccount voyager-wcp-domain-voyager + Normal RBACSuccessful 54s voyager-operator Successfully created Role voyager-wcp-domain-voyager + Normal RBACSuccessful 54s voyager-operator Successfully created RoleBinding voyager-wcp-domain-voyager + Normal DeploymentReconcileSuccessful 54s voyager-operator Successfully created HAProxy Deployment voyager-wcp-domain-voyager + Normal StatsServiceReconcileSuccessful 54s voyager-operator Successfully created stats Service voyager-wcp-domain-voyager-stats + + ``` + {{% /expand %}} + + + +##### Verify Non-SSL and SSL access + +After setting up the Voyager (ingress-based) load balancer, verify that the Oracle WebCenter Portal domain applications are accessible through the load balancer port 30305 (both SSL and non-SSL). The application URLs for Oracle WebCenter Portal domain are: + +> Note: Port 30305 is the LOADBALANCER-Non-SSLPORT and LOADBALANCER-SSLPORT. + +##### Non-SSL configuration + + ```bash + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenter + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/console + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/em + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rsscrawl + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rest + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenterhelp + + ``` +##### SSL configuration + + ```bash + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenter + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/console + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/em + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rest + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp + + ``` + +##### Uninstall the chart + + To uninstall and delete the my-ingress deployment, enter the following command: + + ```bash + $ helm delete wcp-voyager-ingress -n wcpns + $ helm delete voyager-operator -n voyager + + ``` + +#### End-to-end SSL configuration + +##### Install Voyager load balancer for end-to-end SSL + +Install the Voyager load balancer as described [here](#install-the-voyager-load-balancer). + +1. Check the status of the Voyager operator. + + ```bash + $ kubectl get all -n voyager + ``` + Sample output: + + ```bash + NAME READY STATUS RESTARTS AGE + pod/voyager-operator-b84f95f8f-4szhl 1/1 Running 0 43h + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + service/voyager-operator ClusterIP 10.107.201.155 443/TCP,56791/TCP 43h + + NAME READY UP-TO-DATE AVAILABLE AGE + deployment.apps/voyager-operator 1/1 1 1 43h + + NAME DESIRED CURRENT READY AGE + replicaset.apps/voyager-operator-b84f95f8f 1 1 1 43h + ``` +1. For secured access (SSL) to the Oracle WebCenter Portal application, create a certificate and generate Kuberentes secrets: + ```bash + $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" + $ kubectl -n wcpns create secret tls domain1-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + ``` +##### Deploy tls to access services + +1. Deploy tls to securely access the services. Only one application can be configured with ssl-passthrough. A sample tls file for Voyager is shown below for the service `wcp-domain-cluster-wcp-cluster` and port `8889`. All the applications running on port `8889` can be securely accessed through this ingress. For each backend service, create different ingresses as Voyager does not support multiple path/rules with annotation `ssl-passthrough`. + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls + ``` + {{%expand "Click here to see the content of the file voyager-tls.yaml" %}} + ```bash + apiVersion: voyager.appscode.com/v1beta1 + kind: Ingress + metadata: + name: voyager-ssl + namespace: wcpns + annotations: + ingress.appscode.com/type: 'NodePort' + ingress.appscode.com/stats: 'true' + ingress.appscode.com/affinity: 'cookie' + ingress.appscode.com/ssl-passthrough: "true" + spec: + tls: + - secretName: domain1-tls-cert + hosts: + - '*' + rules: + - host: '*' + http: + nodePort: '31443' + paths: + - path: / + backend: + serviceName: wcp-domain-cluster-wcp-cluster + servicePort: '8889' + + ``` + {{% /expand %}} + ```bash + $ kubectl create -f voyager-tls.yaml + ``` + {{%expand "Click here to see the services supported by the ingress" %}} + ```bash + kubectl describe ingress.voyager.appscode.com/voyager-ssl -n wcpns + Name: voyager-ssl + Namespace: wcpns + Labels: + Annotations: ingress.appscode.com/affinity: cookie + ingress.appscode.com/ssl-passthrough: true + ingress.appscode.com/stats: true + ingress.appscode.com/type: NodePort + API Version: voyager.appscode.com/v1beta1 + Kind: Ingress + Metadata: + Creation Timestamp: 2020-07-20T04:34:05Z + Generation: 1 + Managed Fields: + API Version: voyager.appscode.com/v1beta1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:ingress.appscode.com/affinity: + f:ingress.appscode.com/ssl-passthrough: + f:ingress.appscode.com/stats: + f:ingress.appscode.com/type: + f:spec: + .: + f:rules: + f:tls: + Manager: kubectl + Operation: Update + Time: 2020-07-20T04:34:05Z + Resource Version: 340071 + Self Link: /apis/voyager.appscode.com/v1beta1/namespaces/wcpns/ingresses/voyager-ssl + UID: 4a9b2e02-1593-45b3-8ac4-ae1ac0f2832c + Spec: + Rules: + Host: * + Http: + Node Port: 31443 + Paths: + Backend: + Service Name: wcp-domain-cluster-wcp-cluster + Service Port: 8889 + Path: / + Tls: + Hosts: + * + Secret Name: domain1-tls-cert + Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal ServiceReconcileSuccessful 7m37s voyager-operator Successfully created NodePort Service voyager-voyager-ssl + N ormal ConfigMapReconcileSuccessful 7m37s voyager-operator Successfully created ConfigMap voyager-voyager-ssl + Normal RBACSuccessful 7m37s voyager-operator Successfully created ServiceAccount voyager-voyager-ssl + Normal RBACSuccessful 7m37s voyager-operator Successfully created Role voyager-voyager-ssl + Normal RBACSuccessful 7m37s voyager-operator Successfully created RoleBinding voyager-voyager-ssl + Normal DeploymentReconcileSuccessful 7m37s voyager-operator Successfully created HAProxy Deployment voyager-voyager-ssl + Normal StatsServiceReconcileSuccessful 7m37s voyager-operator Successfully created stats Service voyager-voyager-ssl-stats + Normal DeploymentReconcileSuccessful 3m5s voyager-operator Successfully patched HAProxy Deployment voyager-voyager-ssl + ``` + {{% /expand %}} + +##### Verify end-to-end SSL access + +Verify that the Oracle WebCenter Portal domain application URLs are accessible through the SSLPORT `31443`: + ```bash + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenter + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rest + + ``` + +##### Uninstall the Voyager tls + + ```bash + $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls + $ kubectl delete -f voyager-tls.yaml + $ helm delete voyager-operator -n voyager + ``` diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/_index.md new file mode 100644 index 000000000..981518896 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/_index.md @@ -0,0 +1,12 @@ ++++ +title = "Monitor a domain and publish logs" +date = 2019-02-22T15:44:42-05:00 +draft = false +weight = 2 +pre = " " +description = "Monitor Oracle WebCenter Portal and publishing logs to Elasticsearch." ++++ + + + +{{% children style="h4" description="true" %}} diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/_index.md new file mode 100644 index 000000000..356bb1382 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/_index.md @@ -0,0 +1,286 @@ ++++ +title = " Monitor a WebCenter Portal domain" +weight = 1 +pre = "" +description = "Monitor an WebCenter Portal instance using Prometheus and Grafana." ++++ +You can monitor a WebCenter Portal domain using Prometheus and Grafana by exporting the metrics from the domain instance using the WebLogic Monitoring Exporter. This sample shows you how to set up the WebLogic Monitoring Exporter to push the data to Prometheus. + +### Prerequisites + +This document assumes that the Prometheus Operator is deployed on the Kubernetes cluster. If it is not already deployed, follow the steps below for deploying the Prometheus Operator. + +#### Clone the kube-prometheus project +Refer to the compatibility matrix of [Kube Prometheus](https://github.com/coreos/kube-prometheus#kubernetes-compatibility-matrix) and clone the [release](https://github.com/coreos/kube-prometheus/releases) version of the `kube-prometheus` repository according to the Kubernetes version of your cluster. +$ git clone https://github.com/coreos/kube-prometheus.git +``` + +#### Label the nodes +Kube-Prometheus requires all the exporter nodes to be labelled with `kubernetes.io/os=linux`. If a node is not labelled, then you must label it using the following command: + +``` +$ kubectl label nodes --all kubernetes.io/os=linux +``` + +#### Create Prometheus and Grafana resources + +Change to the `kube-prometheus` directory and execute the following commands to create the namespace and CRDs: + +**NOTE**: Wait for a minute for each command to process. + +```bash +$ cd kube-prometheus + +$ kubectl create -f manifests/setup +$ until kubectl get servicemonitors --all-namespaces ; do date; sleep 1; echo ""; done +$ kubectl create -f manifests/ +``` + +#### Provide external access +To provide external access for Grafana, Prometheus, and Alertmanager, execute the commands below: + +```bash +$ kubectl patch svc grafana -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32100 }]' +$ kubectl patch svc prometheus-k8s -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32101 }]' +$ kubectl patch svc alertmanager-main -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32102 }]' +``` + +**NOTE**: + +* `32100` is the external port for Grafana +* `32101` is the external port for Prometheus +* `32102` is the external port for Alertmanager + +-------------- + +## Set Up the WebLogic Monitoring Exporter + +Set up the WebLogic Monitoring Exporter to collect WebLogic Server metrics and monitor your WebCenter Portal domain. + +#### Generate the WebLogic Monitoring Exporter Deployment Package + +Two packages are required as the listening ports are different for the Administration Server and Managed Servers. +One binary required for the Admin Server (`wls-exporter-as.war`) and one for Managed Cluster (`wls-exporter-ms.war`). +Set the required proxies and then run the script `getX.X.X.sh` to generate two binaries: + +```bash +$ cd <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter + +$ sh get1.1.0.sh +``` + +Output: +``` + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed +100 607 0 607 0 0 357 0 --:--:-- 0:00:01 --:--:-- 357 +100 2016k 100 2016k 0 0 398k 0 0:00:05 0:00:05 --:--:-- 797k +-------------------wls-exporter-ms start------------------- +created /tmp/ci-GNysQzP1kv +Copying completed +/tmp/ci-GNysQzP1kv <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter +in temp dir + adding: WEB-INF/weblogic.xml (deflated 66%) + adding: config.yml (deflated 63%) +wls-exporter-ms.war is ready +-------------------wls-exporter-ms end------------------- +-------------------wls-exporter-as start------------------- +Copying completed +in temp dir + adding: WEB-INF/weblogic.xml (deflated 66%) + adding: config.yml (deflated 52%) +wls-exporter-as.war is ready +-------------------wls-exporter-as end------------------- +zip completed +<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter +``` + +#### Copy the WAR Files to the WebLogic Domain Home + +Copy the `wls-exporter-as.war` and `wls-exporter-ms.war` files to the domain home directory in the Administration Server pod. + +``` +$ kubectl cp wls-exporter-as.war wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/ + +$ kubectl cp wls-exporter-ms.war wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/ +``` + +#### Deploy the WebLogic Monitoring Exporter + +Follow these steps to deploy the package in the WebLogic Server instances: + +1. On the Administration Server and Managed Servers, deploy the WebLogic Monitoring Exporter (`wls-exporter-ms.war`) separately using the Oracle Enterprise Manager. + + ![Wme-Deploy](images/wme-deploy.png) + +1. Select the servers to which the Exporter WAR should be deployed: + + ![Wme-Deploy-Target-Server](images/wme-deploy-target-server.png) + +1. Set the application name. The application name must be different if it is deployed separately in the Administration Server and Managed Servers. Make sure the context-root for both the deployments is `wls-exporter`: + + ![Wme-Deploy-Contextroot](images/wme-deploy-contextroot.png) + +1. Click **Install and start application**. + +1. Then deploy the WebLogic Monitoring Exporter application (`wls-exporter-ms.war`). + +1. Activate the changes to start the application. If the application is started and the port is exposed, +then you can access the WebLogic Monitoring Exporter console using this URL: `http:///wls-exporter`. + + ![Wme-Test-Url](images/wme-test-url.png) + +1. Repeat same steps for `wls-exporter-as.war`. + +#### Configure Prometheus Operator +Prometheus enables you to collect metrics from the WebLogic Monitoring Exporter. The Prometheus Operator identifies the targets using service discovery. In order to Prometheus be able to discovery and scrape services inside the additional namespaces like `wcpns`, you must create a service monitor resource pointing to the services in `wcpns` namespace. + +See the following sample service monitor deployment YAML configuration file located at + +`<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml`. + +`ServiceMonitor` for wls-exporter: +``` +apiVersion: v1 +kind: Secret +metadata: + name: basic-auth + namespace: monitoring +data: + password: d2VsY29tZTEK # welcome1 i.e.'WebLogic password' + user: d2VibG9naWM= # weblogic i.e. 'WebLogic username' +type: Opaque +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: wls-exporter-wcp-domain + namespace: monitoring + labels: + k8s-app: wls-exporter +spec: + namespaceSelector: + matchNames: + - wcpns + selector: + matchLabels: + weblogic.domainName: wcp-domain + endpoints: + - basicAuth: + password: + name: basic-auth + key: password + username: + name: basic-auth + key: user + port: default + relabelings: + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + interval: 10s + honorLabels: true + path: /wls-exporter/metrics +``` + +To export metrics using `wls-exporter,` you need to set basicAuth in Prometheus. So create a Kubernetes `Secret` with the user name and password that are `base64` encoded. This Secret will be used in the ServiceMonitor deployment. + +When generating the base64 encoded strings for the user name and password, observe if a new line character is appended in the encoded string. This line character causes an authentication failure. To avoid a new line string, use the following example: + +``` +$ echo -n "Welcome1" | base64 +V2VsY29tZTE= +``` + +In the deployment YAML configuration for `wls-exporter` shown above, `weblogic.domainName: wcp-domain` is used as a label under `spec.selector.matchLabels`, so all the services are selected for the service monitor. If you don't use this label, you should create separate service monitors for each server--if the server name is used as matching labels in `spec.selector.matchLabels`. Doing so will require you to relabel the configuration because Prometheus, by default, ignores the labels provided in the *wls-exporter*. + +By default, Prometheus does not store all the labels provided by the target. In the service monitor deployment YAML configuration, you must mention the relabeling configuration (`spec.endpoints.relabelings`) so that certain labels provided by `weblogic-monitoring-exporter` (required for the Grafana dashboard) are stored in Prometheus. Do not delete the following section from the configuration YAML file: +``` +relabelings: + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) +``` + +#### Add `RoleBinding` and `Role` for the WebLogic Domain Namespace + +The RoleBinding is required for Prometheus to access the endpoints provided by the WebLogic Monitoring Exporter. You need to add RoleBinding for the namespace under which the WebLogic Servers pods are running in the Kubernetes cluster. Edit the `kube-prometheus/manifests/prometheus-roleBindingSpecificNamespaces.yaml` file in the Prometheus Operator deployment manifests and add the `RoleBinding` for the namespace (`wcpns`) similar to the following example: + +``` +- apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: prometheus-k8s + namespace: wcpns + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: prometheus-k8s + subjects: + - kind: ServiceAccount + name: prometheus-k8s + namespace: monitoring +``` +In the Prometheus Operator deployment manifests located at `kube-prometheus/manifests/prometheus-roleSpecificNamespaces.yaml,` add the `Role` for the namespace `wcpns` under which the WebLogic Servers pods are running in the Kubernetes cluster. See the following example: +``` +- apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: prometheus-k8s + namespace: wcpns + rules: + - apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch +``` +Then apply `prometheus-roleBindingSpecificNamespaces.yaml` and `prometheus-roleSpecificNamespaces.yaml` for the `RoleBinding` and `Role` to take effect in the cluster. +``` +$ kubectl apply -f kube-prometheus/manifests/prometheus-roleBindingSpecificNamespaces.yaml + +$ kubectl apply -f kube-prometheus/manifests/prometheus-roleSpecificNamespaces.yaml +``` +#### Deploy the Service Monitor + +To deploy the service monitor, use the above `wls-exporter.yaml` deployment YAML and run the following command: +``` +$ kubectl create -f <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml +``` +#### Enable Prometheus to Discover the Service + +After deploying the service monitor, Prometheus should be able to discover *wls-exporter* and export metrics. + +You can access the Prometheus dashboard at `http://mycompany.com:32101/`. + +![Wme-Service-Discovery](images/wme-service-discovery.png) + + +#### Deploy Grafana Dashboard + +To view the domain metrics, deploy the Grafana dashboard provided in the [WebLogic Monitoring Exporter](https://github.com/oracle/weblogic-monitoring-exporter/tree/master/samples/kubernetes/end2end#monitoring-weblogic-server-with-the-grafana-dashboard). + +You can access the Grafana dashboard at `http://mycompany.com:32100/`. + +1. Log in to Grafana dashboard with `admin/admin`. +1. Go to **Settings**, then select **DataSources**, and then **Add Data Source**. + + HTTP URL: Prometheus URL `http://mycompany.com:32101/` + + Auth: Enable Basic Auth + + Basic Auth Details: Weblogic credentials provided in the step [Configure Prometheus Operator](#configure-prometheus-operator) + + ![Wme-GP-Add-Datasource](images/wme-gp-add-datasource.png) + +1. Download the `weblogic_dashboard.json` file from [here](weblogic_dashboard.json). +1. Click **Add** and then **Import**. Paste the modified JSON in the **Paste JSON** block, and then load it. + + ![Wme-GP-Import-Json](images/wme-gp-import-json.png) + + This displays the WebLogic Server Dashboard. + + ![Wme-GP-WLS-Dashboard](images/wcp-graphana-dashboard.png) \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wcp-graphana-dashboard.png b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wcp-graphana-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..f2979fb8dd305b985d684140ecc9b4a498d4288f GIT binary patch literal 216980 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ʕ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

J^gs5-{fM;qR+z##=;@ze0$; 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

9~^%HC*I)rR`VmCe(O} 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 D6jg-@ literal 0 HcmV?d00001 diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-gp-import-json.png b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-gp-import-json.png new file mode 100644 index 0000000000000000000000000000000000000000..777daa9743902c20cbe055395947ed30b004f84a GIT binary patch literal 34638 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 z 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 literal 0 HcmV?d00001 diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-test-url.png b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-test-url.png new file mode 100644 index 0000000000000000000000000000000000000000..30acc2e5b37f4d1530a9c91d87bc5dc280f22f4b GIT binary patch literal 64502 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 literal 0 HcmV?d00001 diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/weblogic_dashboard.json b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/weblogic_dashboard.json new file mode 100644 index 000000000..e68f7a964 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/weblogic_dashboard.json @@ -0,0 +1,3312 @@ +{ + "__inputs": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "5.2.4" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "5.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1563266678971, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 32, + "panels": [], + "title": "Servers", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 13, + "x": 0, + "y": 1 + }, + "hideTimeOverride": true, + "id": 16, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(count (wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"}) by (name))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{weblogic_serverName}}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Running Servers", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 11, + "x": 13, + "y": 1 + }, + "id": 23, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(count(wls_webapp_config_deployment_state{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"}) by (app))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Deployed Applications", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "hideTimeOverride": true, + "id": 104, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "weblogic_serverName", + "targets": [ + { + "expr": "wls_server_activation_time{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\",weblogic_serverName=\"$serverName\"}", + "format": "table", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Server Name", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#56A64B", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 6, + "y": 4 + }, + "id": 84, + "interval": "", + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "wls_server_state_val{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Server Status", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "SHUTDOWN", + "value": "0" + }, + { + "op": "=", + "text": "STARTING", + "value": "1" + }, + { + "op": "=", + "text": "RUNNING", + "value": "2" + }, + { + "op": "=", + "text": "STANDBY", + "value": "3" + }, + { + "op": "=", + "text": "FAILED", + "value": "8" + }, + { + "op": "=", + "text": "FAILED", + "value": "17" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 10, + "y": 4 + }, + "hideTimeOverride": true, + "id": 27, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "100 - wls_jvm_heap_free_percent{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Heap Usage", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 14, + "y": 4 + }, + "hideTimeOverride": true, + "id": 91, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Running Time", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "description": "", + "format": "short", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 19, + "y": 4 + }, + "hideTimeOverride": true, + "id": 96, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "wls_server_open_sockets_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Open Sockets", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "aliasColors": { + " heap free managed-server-1": "super-light-green", + " heap free managed-server-2": "dark-green", + "heap size managed-server-1 ": "super-light-red", + "heap size managed-server-2 ": "dark-red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_jvm_heap_free_current{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " Heap Free ({{weblogic_serverName}})", + "refId": "B" + }, + { + "expr": "wls_jvm_heap_size_current{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "Heap Size ({{weblogic_serverName}})", + "refId": "A" + }, + { + "expr": "wls_jvm_heap_size_max{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "Heap Max ({{weblogic_serverName}})", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JVM Heap", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + " heap free managed-server-1": "super-light-green", + " heap free managed-server-2": "dark-green", + "heap size managed-server-1 ": "super-light-red", + "heap size managed-server-2 ": "dark-red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 21, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_jvm_process_cpu_load{weblogic_domainUID=~\"$domainName\", weblogic_clusterName=~\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"} * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " {{weblogic_serverName}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Load", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_threadpool_execute_thread_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total Threads ({{weblogic_serverName}})", + "refId": "A" + }, + { + "expr": "wls_threadpool_stuck_thread_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Stuck Threads ({{weblogic_serverName}})", + "refId": "D" + }, + { + "expr": "wls_threadpool_queue_length{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "queue", + "refId": "C" + }, + { + "expr": "wls_threadpool_hogging_thread_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "hogging", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Thread Pool", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 35, + "panels": [ + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 28 + }, + "hideTimeOverride": true, + "id": 126, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Sessions", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_webapp_config_sessions_opened_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Sessions (top $topN)", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 28 + }, + "hideTimeOverride": true, + "id": 136, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Requests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_servlet_invocation_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Requests (top $topN)", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 28 + }, + "hideTimeOverride": true, + "id": 134, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Time", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "ms" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_servlet_execution_time_total{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Execution Time (top $topN)", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_webapp_config_open_sessions_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{app}}", + "refId": "A" + }, + { + "expr": "", + "format": "time_series", + "intervalFactor": 1, + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Current Sessions ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 128, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": " sum(irate(wls_webapp_config_sessions_opened_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (app)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{app}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Session Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 132, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(wls_servlet_execution_time_average{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app)) / (count(wls_servlet_execution_time_average{weblogic_domainUID=\"domain1\", weblogic_clusterName=\"cluster-1\"}) by (app))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{app}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Execution Time per Request ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 138, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_servlet_invocation_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (app)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{app}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Request Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Web Applications", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 43, + "panels": [ + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 29 + }, + "hideTimeOverride": true, + "id": 111, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Server", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "weblogic_serverName", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Name", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "name", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Active Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Current Capacity", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_datasource_curr_capacity{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "C" + }, + { + "expr": "sum(wls_datasource_active_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_datasource_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Overview", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 13, + "x": 0, + "y": 33 + }, + "id": 50, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_active_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " {{name}} @ {{weblogic_serverName}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 11, + "x": 13, + "y": 33 + }, + "id": 71, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(wls_datasource_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " {{name}} @ {{weblogic_serverName}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connection Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 9, + "w": 11, + "x": 0, + "y": 41 + }, + "id": 46, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_waiting_for_connection_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " {{name}} @ {{weblogic_serverName}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pending Connection Requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 9, + "w": 13, + "x": 11, + "y": 41 + }, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_connection_delay_time{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " {{name}} @ {{weblogic_serverName}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average Connection Delay Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Data Sources", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 40, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 145, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jmsruntime_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{weblogic_serverName}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JMS Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 147, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jmsruntime_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (weblogic_serverName)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{weblogic_serverName}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JMS Connection Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 36 + }, + "hideTimeOverride": true, + "id": 113, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Name", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "jmsserver", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Current Dests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Total Dests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_jms_destinations_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + }, + { + "expr": "sum(wls_jms_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_jms_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "sum(wls_jms_destinations_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "E" + }, + { + "expr": "sum(wls_jms_destinations_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "F" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "JMSServer Overview", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 54, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jms_messages_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Current ({{jmsserver}})", + "refId": "A" + }, + { + "expr": "sum(wls_jms_messages_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pending ({{jmsserver}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Messages", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 56, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jms_bytes_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Current ({{jmsserver}})", + "refId": "A" + }, + { + "expr": "sum(wls_jms_bytes_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pending ({{jmsserver}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bytes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 58, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jms_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{jmsserver}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Message Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 117, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jms_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{jmsserver}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Byte Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 54 + }, + "hideTimeOverride": true, + "id": 119, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 3, + "desc": false + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Destination", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "destination", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Current Consumers", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Current Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Pending Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Currrent Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Pending Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #F", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #G", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_jms_dest_consumers_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_jms_dest_messages_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + }, + { + "expr": "sum(wls_jms_dest_messages_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "C" + }, + { + "expr": "sum(wls_jms_dest_bytes_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "sum(wls_jms_dest_bytes_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "E" + }, + { + "expr": "sum(wls_jms_dest_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(wls_jms_dest_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "G" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Destinations Overview", + "transform": "table", + "type": "table" + } + ], + "title": "JMS Services", + "type": "row" + } + ], + "refresh": false, + "schemaVersion": 16, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "prometheus", + "value": "Prometheus-1" + }, + "hide": 0, + "label": null, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "Domain", + "multi": false, + "name": "domainName", + "options": [], + "query": "label_values(weblogic_domainUID)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "Cluster", + "multi": false, + "name": "clusterName", + "options": [], + "query": "label_values(wls_jvm_uptime{weblogic_domainUID=\"$domainName\"},weblogic_clusterName)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": "Server", + "multi": true, + "name": "serverName", + "options": [], + "query": "label_values(wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"},weblogic_serverName)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "tags": [], + "text": "5", + "value": "5" + }, + "hide": 0, + "includeAll": false, + "label": "Top N", + "multi": false, + "name": "topN", + "options": [ + { + "selected": false, + "text": "3", + "value": "3" + }, + { + "selected": true, + "text": "5", + "value": "5" + }, + { + "selected": false, + "text": "7", + "value": "7" + }, + { + "selected": false, + "text": "10", + "value": "10" + } + ], + "query": "3, 5, 7, 10", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "hidden": false, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "WebLogic Server Dashboard", + "uid": "5yUwzbZWz", + "version": 6 +} \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/_index.md new file mode 100644 index 000000000..297d4d4ac --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/_index.md @@ -0,0 +1,11 @@ ++++ +title = "Publish WebLogic Server logs into Elasticsearch" +date = 2019-02-22T15:44:42-05:00 +draft = false +weight = 2 +pre = " " +description = "Publish WebLogic Server logs into Elasticsearch." ++++ + +To publish WebLogic Server logs into Elasticsearch, you can configure your WebCenter Portal domain to use Fluentd or WebLogic Logging Exporter. +{{% children style="h4" description="true" %}} diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/_index.md new file mode 100644 index 000000000..bbb1c6213 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/_index.md @@ -0,0 +1,382 @@ ++++ +title = " Fluentd" +weight = 1 +pre = "a. " +description = "Describes how to configure a WebCenter Portal domain to use Fluentd to send log information to Elasticsearch." ++++ + +#### Overview +You can configure your WebLogic domain to use *Fluentd* so it can send the log information to Elasticsearch. + +Here's how this works: + +* `fluentd` runs as a separate container in the Administration Server and Managed Server pods. +* The log files reside on a volume that is shared between the `weblogic-server` and `fluentd` containers. +* `fluentd` tails the domain logs files and exports them to Elasticsearch. +* A `ConfigMap` contains the filter and format rules for exporting log records. + + +##### Prerequisites + +It is assumed that you are editing an existing WebCenter Portal domain. However, you can make all the changes to the domain YAML before creating the domain. +A complete example of a domain definition with fluentd configuration is at the [end of this document](#domain-example). + +{{% notice note %}} These identifiers are used in the sample commands. +* `wcpns`: WebCenter Portal domain namespace +* `wcp-domain`: `domainUID` +* `wcpinfra-domain-credentials`: Kubernetes secret +{{%/notice %}} + +The sample Elasticsearch configuration is: +```text + elasticsearchhost: elasticsearch.wcp-domain.sample.com + elasticsearchport: 443 + elasticsearchuser: username + elasticsearchpassword: password +``` + +#### Install Elasticsearch and Kibana + +To install Elasticsearch and Kibana, run the following command: +```bash +$ kubectl apply -f kubernetes/samples/scripts/elasticsearch-and-kibana/elasticsearch_and_kibana.yaml +``` + +#### Configure log files to use a volume +The domain log files must be written to a volume that can be shared between the `weblogic-server` and `fluentd` containers. The following elements are required to accomplish this: + +* `logHome` must be a path that can be shared between containers. +* `logHomeEnabled` must be set to `true` so that the logs are written outside the pod and persist across pod restarts. +* A `volume` must be defined on which the log files will reside. In the example, `emptyDir` is a volume that gets created when a Pod is created. It will persist across pod restarts but deleting the pod would delete the `emptyDir` content. +* The `volumeMounts` mounts the named volume created with `emptyDir` and establishes the base path for accessing the volume. + +**NOTE**: For brevity, only the paths to the relevant configuration are here. + +For Example, run : `kubectl edit domain wcp-domain -n wcpns` and make the following edits: + +```yaml +spec: + logHome: /u01/oracle/user_projects/domains/logs/wcp-domain + logHomeEnabled: true + serverPod: + volumes: + - emptyDir: {} + name: weblogic-domain-storage-volume + volumeMounts: + - mountPath: /scratch + name: weblogic-domain-storage-volume +``` + +#### Add Elasticsearch secrets to WebLogic domain credentials +Configure the `fluentd` container to look for Elasticsearch parameters in the domain credentials. Edit the domain credentials and add the parameters shown in the example below. + +For example, run: `kubectl edit secret wcpinfra-domain-credentials -n wcpns` and add the base64 encoded values of each Elasticsearch parameter: +```text +elasticsearchhost: ZWxhc3RpY3NlYXJjaC5ib2JzLWJvb2tzLnNhbXBsZS5jb20= +elasticsearchport: NDQz +elasticsearchuser: Ym9i +elasticsearchpassword: d2VsY29tZTE= +``` + +#### Create Fluentd configuration +Create a `ConfigMap` named `fluentd-config` in the namespace of the domain. The `ConfigMap` contains the parsing rules and Elasticsearch configuration. + +Here's an explanation of some elements defined in the `ConfigMap`: + +* The `@type tail` indicates that `tail` is used to obtain updates to the log file. +* The `path` of the log file obtained from the `LOG_PATH` environment variable that is defined in the `fluentd` container. +* The `tag` value of log records obtained from the `DOMAIN_UID` environment variable that is defined in the `fluentd` container. +* The `` section defines how to interpret and tag each element of a log record. +* The `` section contains the configuration information for connecting to Elasticsearch and defines the index name of each record to be the `domainUID.` +* The `scheme` indicates type of connection between fluentd and Elasticsearch. + +The following is an example of how to create the `ConfigMap`: +```bash +cat < + @type null + + + @type tail + path "#{ENV['LOG_PATH']}" + pos_file /tmp/server.log.pos + read_from_head true + tag "#{ENV['DOMAIN_UID']}" + # multiline_flush_interval 20s + + @type multiline + format_firstline /^####/ + format1 /^####<(?(.*?))>/ + format2 / <(?(.*?))>/ + format3 / <(?(.*?))>/ + format4 / <(?(.*?))>/ + format5 / <(?(.*?))>/ + format6 / <(?(.*?))>/ + format7 / <(?(.*?))>/ + format8 / <(?(.*?))>/ + format9 / <(?(.*?))>/ + format10 / <(?(.*?))>/ + format11 / <(?(.*?))>/ + format12 / <(?(.*?))>/ + format13 / <(?(.*?))>/ + + + + @type elasticsearch + host "#{ENV['ELASTICSEARCH_HOST']}" + port "#{ENV['ELASTICSEARCH_PORT']}" + user "#{ENV['ELASTICSEARCH_USER']}" + password "#{ENV['ELASTICSEARCH_PASSWORD']}" + index_name "#{ENV['DOMAIN_UID']}" + scheme http + +EOF +``` + +#### Mount the ConfigMap as a volume in the `weblogic-server` container +Edit the domain definition and configure a volume for the `ConfigMap` containing the `fluentd` configuration. + +**NOTE**: For brevity, only the paths to the relevant configuration are shown. + +For example, run: `kubectl edit domain wcp-domain -n wcpns` and add the following portions to the domain definition. +```yaml +spec: + serverPod: + volumes: + - configMap: + defaultMode: 420 + name: fluentd-config + name: fluentd-config-volume +``` + +#### Add `fluentd` container +Add a container to the domain to run `fluentd` in the Administration Server and Managed Server pods. + +The container definition: + +* Defines a `LOG_PATH` environment variable that points to the log location of `bobbys-front-end`. +* Defines `ELASTICSEARCH_HOST`, `ELASTICSEARCH_PORT`, `ELASTICSEARCH_USER`, and `ELASTICSEARCH_PASSWORD` environment variables that are all retrieving their values from the secret `wcpinfra-domain-credentials`. +* Includes volume mounts for the `fluentd-config` `ConfigMap` and the volume containing the domain logs. + +**NOTE**: For brevity, only the paths to the relevant configuration are shown. + +For example, run: `kubectl edit domain wcp-domain -n wcpcns` and add the following container definition. +```yaml +spec: + serverPod: + containers: + - args: + - -c + - /etc/fluent.conf + env: + - name: DOMAIN_UID + valueFrom: + fieldRef: + fieldPath: metadata.labels['weblogic.domainUID'] + - name: SERVER_NAME + valueFrom: + fieldRef: + fieldPath: metadata.labels['weblogic.serverName'] + - name: LOG_PATH + value: /u01/oracle/user_projects/domains/logs/wcp-domain/$(SERVER_NAME).log + - name: FLUENTD_CONF + value: fluentd.conf + - name: FLUENT_ELASTICSEARCH_SED_DISABLE + value: "true" + - name: ELASTICSEARCH_HOST + valueFrom: + secretKeyRef: + key: elasticsearchhost + name: wcpinfra-domain-credentials + - name: ELASTICSEARCH_PORT + valueFrom: + secretKeyRef: + key: elasticsearchport + name: wcpinfra-domain-credentials + - name: ELASTICSEARCH_USER + valueFrom: + secretKeyRef: + key: elasticsearchuser + name: wcpinfra-domain-credentials + optional: true + - name: ELASTICSEARCH_PASSWORD + valueFrom: + secretKeyRef: + key: elasticsearchpassword + name: wcpinfra-domain-credentials + optional: true + image: fluent/fluentd-kubernetes-daemonset:v1.3.3-debian-elasticsearch-1.3 + imagePullPolicy: IfNotPresent + name: fluentd + resources: {} + volumeMounts: + - mountPath: /fluentd/etc/fluentd.conf + name: fluentd-config-volume + subPath: fluentd.conf + - mountPath: /scratch + name: weblogic-domain-storage-volume +``` + +#### Verify logs exported to Elasticsearch + +The logs are sent to Elasticsearch after you start the Administration Server and Managed Server pods after making the changes described previously. + +You can check if the `fluentd` container is successfully tailing the log by executing a command like `kubectl logs -f wcp-domain-adminserver -n wcpns fluentd`. The log output should look similar to this: +```text +2019-10-01 16:23:44 +0000 [info]: #0 starting fluentd worker pid=13 ppid=9 worker=0 +2019-10-01 16:23:44 +0000 [warn]: #0 /scratch/logs/bobs-bookstore/managed-server1.log not found. Continuing without tailing it. +2019-10-01 16:23:44 +0000 [info]: #0 fluentd worker is now running worker=0 +2019-10-01 16:24:01 +0000 [info]: #0 following tail of /scratch/logs/bobs-bookstore/managed-server1.log +``` + +When you connect to Kibana, you will see an index created for the `domainUID`. + +#### Domain example + +The following is a complete example of a domain custom resource with a `fluentd` container configured. + +```yaml +apiVersion: weblogic.oracle/v8 +kind: Domain +metadata: + labels: + weblogic.domainUID: wcp-domain + name: wcp-domain + namespace: wcpns +spec: + domainHome: /u01/oracle/user_projects/domains/wcp-domain + domainHomeSourceType: PersistentVolume + image: "oracle/wcportal:12.2.1.4" + imagePullPolicy: "IfNotPresent" + webLogicCredentialsSecret: + name: wcpinfra-domain-credentials + includeServerOutInPodLog: true + logHomeEnabled: true + httpAccessLogInLogHome: true + logHome: /u01/oracle/user_projects/domains/logs/wcp-domain + dataHome: "" + serverStartPolicy: "IF_NEEDED" + adminServer: + serverStartState: "RUNNING" + clusters: + - clusterName: wcp_cluster + serverStartState: "RUNNING" + serverPod: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: "weblogic.clusterName" + operator: In + values: + - $(CLUSTER_NAME) + topologyKey: "kubernetes.io/hostname" + replicas: 2 + serverPod: + containers: + - args: + - -c + - /etc/fluent.conf + env: + - name: DOMAIN_UID + valueFrom: + fieldRef: + fieldPath: metadata.labels['weblogic.domainUID'] + - name: SERVER_NAME + valueFrom: + fieldRef: + fieldPath: metadata.labels['weblogic.serverName'] + - name: LOG_PATH + value: /u01/oracle/user_projects/domains/logs/wcp-domain/$(SERVER_NAME).log + - name: FLUENTD_CONF + value: fluentd.conf + - name: FLUENT_ELASTICSEARCH_SED_DISABLE + value: "true" + - name: ELASTICSEARCH_HOST + valueFrom: + secretKeyRef: + key: elasticsearchport + name: wcpinfra-domain-credentials + - name: ELASTICSEARCH_PORT + valueFrom: + secretKeyRef: + key: elasticsearchhost + name: wcpinfra-domain-credentials + - name: ELASTICSEARCH_USER + valueFrom: + secretKeyRef: + key: elasticsearchuser + name: wcpinfra-domain-credentials + - name: ELASTICSEARCH_PASSWORD + valueFrom: + secretKeyRef: + key: elasticsearchpassword + name: wcpinfra-domain-credentials + image: fluent/fluentd-kubernetes-daemonset:v1.11.5-debian-elasticsearch6-1.0 + imagePullPolicy: IfNotPresent + name: fluentd + resources: {} + volumeMounts: + - mountPath: /fluentd/etc/fluentd.conf + name: fluentd-config-volume + subPath: fluentd.conf + - mountPath: /u01/oracle/user_projects/domains + name: weblogic-domain-storage-volume + env: + - name: JAVA_OPTIONS + value: -Dweblogic.StdoutDebugEnabled=false + - name: USER_MEM_ARGS + value: '-Djava.security.egd=file:/dev/./urandom -Xms1g -Xmx2g' + volumeMounts: + - mountPath: /u01/oracle/user_projects/domains + name: weblogic-domain-storage-volume + volumes: + - name: weblogic-domain-storage-volume + persistentVolumeClaim: + claimName: wcp-domain-domain-pvc + - emptyDir: {} + name: weblogic-domain-storage-volume + - configMap: + defaultMode: 420 + name: fluentd-config + name: fluentd-config-volume + serverStartPolicy: IF_NEEDED + webLogicCredentialsSecret: + name: wcpinfra-domain-credentials +``` + +##### Get the Kibana dashboard port information as shown below: + +```bash +-bash-4.2$ kubectl get pods -w +NAME READY STATUS RESTARTS AGE +elasticsearch-8bdb7cf54-mjs6s 1/1 Running 0 4m3s +kibana-dbf8964b6-n8rcj 1/1 Running 0 4m3s +``` + +```bash +-bash-4.2$ kubectl get svc +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +elasticsearch ClusterIP 10.100.11.154 9200/TCP,9300/TCP 4m32s +kibana NodePort 10.97.205.0 5601:31884/TCP 4m32s +kubernetes ClusterIP 10.96.0.1 443/TCP 71d +``` +You can access the Kibana dashboard at `http://mycompany.com:kibana-nodeport/`. In our example, the node port is 31884. + +#### Create an Index Pattern in Kibana +Create an index pattern `wcp-domain*` in Kibana by navigating to the dashboard through the Management option. When the servers are started, the log data is shown on the Kibana dashboard. + +![WCP-Kibana-Dashboard](wcp-kibana-dashboard.png) \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/wcp-kibana-dashboard.png b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/wcp-kibana-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..da346b6fa42ad3b579331e51d2bc66930ca8322f GIT binary patch literal 159602 zcmdqI2UkXb zO+pETUIT=d1PCN=yzl#*=RD_q$M*xiHAcqHUfEe?uDRx%>$>KC`@l$_ot2*z006KX z+|hjm05C@Y01QuAm}oT-4!^Bw7drn(`nLdOD8W_Q4WsK#!lfHK> z`~iUTm;Zd|3?5zD0syFa2D&$&1lz73pZaJLkcB^mjs-1s_PzyeLIvcWH#yE_d|69< z+ak2g_Pkh3)v=EI+z9%&t_k7Cr_I%TpMbi8p6j?Lb>^0LO(NrS+VqQkKR9O)PW9ZFwj|fc`@1eJpV>b73r@iu z+j-)Tshd*S=aV8=i>g)@_d0D>vO-^kc+#7`#&EqUY>05kGxJNd(l+-KkJ{wpBr0} z{{L0A%fWh8e;Uly0Px|B$*KRG?1btj%g1adwP4_Qp>_uSxNHlld7rJhcEVTg%}~!4LU=1@7s*>w9x-g>kahfWsWi#{S^>&JsB<5nZ9?U?nP;q*kg#?!?K2J zmiQ6*S)Rwvs5JPHD^#W7$X6qMxJRN$6d*jNrZ4^>{epjBC+V9balbhE-@5fcQmCp% zy3|6w9YLpe4%~#lRFJ8L(PI(umH-zOj-)5&P@3Xboiq!nqz#ae#%$RdcVw);@gJy{? z2y1`PK8d#gR$_8~IwW$JVZX$=J>KVIQ9Lw}mE&^I|$@r@AH=U{vn~La>C?_G#d4p3gFUL)m?+ z=L`GUQXk{yz2se=4%{qE+nuOeQifz<&pQnKaEGq^95LU$PvkERvyz#@rYBJ8hRLm94BX!d<>>$Y0EJud2$$ZAF-~rnwNtx- zq_&uYkA4&ll_FE+EB2%8Cofr8?8__7O#P5xbVfij?`NJXty@h&@v!vIl_SF|!FRU_ zCx?^o;Y{&;Zo7V|V5o^!R0jRbOZfZ6M!|o}?Nk&XI74~eb#G7RBk zeO7Jr3*PSq>3qFDYyj%FH7eMG@sIhn^fsC_Gr=q0nQ7!j_0M+SO$;;DX zr)zEE2LQqN1ns@J_n1KKBSlNj8O=)oy&uKUbjhiq+J+Y_iz_@2TNbg+#OohL^qdJD z?hY0|znUG-hAlgKQf=L*CZrkO5;ikoKB_kl=3){!+&Sz7RLTr2GY7vgW8JSM$~0wq z115*XPkCo@F-;9V7-EJ?8*z~bsRGO#;!4XJe`=wQ6^t0?Z_fDlru=I9 z>W1Uz`;89~{zjjZx;jo8utYF0O?)@#Kvq9QF&%!7*T0|th{dhU>$9okh58{0A!FO+ zx|I80rXEhz(u+^YSTEaTuWHY&;0(3m?qgC}B1)X4m|NMW-{whZ-KFVH@2A>CuAM!! znv2ZryMElKMQjDHj3LR0wA5sjEOOGWKN3r51NE}7M+j_VZ_$j=ikf+Sn@59iYk^%X zIOJLLppe~F72V;}2V}V8D<3X zS74^FWPwea>(Ubm!F_)2hd)QK@*g;-DrArhL-5B)6{Ie{=53Ybcf(~f?UQv%M>9F_ zugj(0go2tfTPZ_+Woly-fcJ0ltckNIrhO+Q%z!rc?P|y1sg?BhLZQSc@rLVb7I{EN z*ScS}r1vO}kGv4L=DVv2q^=qjABu|3&6V~@7>*qS5qoSczUIPgluXd1Xjm%S z9gNiRL+b0#yPGNt#uhT+wwa#0aqgw4zWy=%-S`9uSb}NeHieTSaXw2dlu&b3d*26; z6OjvT-?e4YE!*qHj%<69qBVH#rJJ0DvE2zG-*qR(8GOrqWe09}aY>+Pa()c*z!VFz z2^PEuV#>lcSf@=cM`0(Vq$|?(=k1wWZ(7a&$YVYRIi#EQi;HhYF+)Y(Kl!~XW?l>N z*^6^Tt_KTw4^>`W4x72-+1$}%oZmACUERnm2wH21?ZNFx^mvg%F7{F6nLCDUq=(MJzkyvtQ#tps>{>?`7SoTo zp6B(g!qd0Ep{X|-ziySlw$Jcr0N=vvz67Pc6R~XZkCYl~93|(d!&PwiU5V@rnT#Ddu+ z3#^Xt+w&zXT1VK_>A^13D4J3=KT3n-bUh1uR=;xL$sIm*1=crHBCqvDJ5A0wuU$NL z2q`Je2#=fw*eL_}IGWYJZ^#unynR32QMRW_WpG4EoxGtOwKON}!v zJnnnWigC}EvACXaByuD}%yt}a42`?b9%GIYycYgtCHQ`wblxT}iO)M)6z`>p+YLgn`?lZjO^%UZK#7<=6Dj#6kw4#yR2 zMS5+^_k=sYhiy|3=13e+0^0FT|AlaM*t0uC_eSY+FP`#whgvNt`(TbppZrE&25G;^ zI!Le10jLU|czVR(h5d9ga=9e!dtY&xJ3d{s8&How11x(V8Gb;Rn|qEOw+Wk;n(Qz8 zWZ)3a^`)Fe~&a4UD^%Z=u41VazI}!RMn95cQH#|?)ahw)^f3Fr;imbAN zlSf`}0p$ukrBR08=0NQ?e0>IMkMnuj)rFhg0VmgS9h+*yjbb zMr98i-Kn7MVE3%N4Z3dpVVi=)v2gaRWQXzZO}U$C%4S0mGtZsBE>xHdO^f$6`gq6V zrrI1UdLMQ-&%?Yf)HePY({Op~(3DF&?$;$v(o&UYSNA^1 z>RzapURzs$%n!?iVhy8*AY-LJR!MPdxKV+Uf}989A72sFpO2v*d|r{|4E(5i=`QJB zD5pWj=$5Kcec&sak8vSAV%MRFpoT8=ee=yo&+9Os_WjHUz){X`2Hk!og8rc|SJ>PK zt6#?@|9}YR251CZV}so%)=HK5^C_JR4I?7IUyr^5WyfxgV3m^8{BGz8Ecu@KaF!eG zuKmSOA9k+9&>VK~Gy8RvJnvZXsQ&gB32NM@off`NY!M9Y%HF&BdO!Wm<=6L;ye-NC z7K_E*p^CkGb@&);KxoZRoNLdjO#$U;gQCG-9r z(vWgkrwC{{oOqklp;{ftCt|K`adntrcB>+!ELos3`jp>E?LEd0)5OzcdLak+s%v=g zyDXdMP>M(K9$(krY5*WS+BsHYW9XF7F{={QU|a1K(T{nFH|ZPV24}O=w+cLE@4ne_ z{KSH4Fi@q8W)aY0EuN*1na7>-Vx6dZzP%J#)KQ*)hTt72(9<#R&c-0bMqL*wSlQZx zrW9chH?Y;KNIs)idi%Oo2G<^vA8FoUN&X~%sh&d)O5Pw|f)Q13)A{~caTX>gpZ)cP zuR1^OuBv)7J`#Kh5_jd*j?hh~PEEy3?`IUfmP7vKAmhc<(1n)}Dd-*p4jfYs2otOo&rjN#)l`qEZq z9~^6hT{wjFCV-M|wP{Y9Ek*EB>ucmBPU7bTrXdWjkOjc=I>-noD>TXT!zxBT+Os~Gdu9N~8 z>)%EABti0NzWV3EH9myf0A#Mz5!&{wKFS`@}2l`ByxqfKfF&X&H~8AURn#?Qo=Q0 z>1Hcr_=vzunm)1Tm0g%x-N{ddv+rtzCtB3LK;HF|3<%A0&BFLvy<1k!&<;4@K!X)o z+O(MSqo563ga?Lz2%XmXMS9m7vEgNQU^@Oi>@Z`fJMZW)Y{7dXOq7(zu zj-pNQ8ew}3?l=vveal)@Wk=^~yT46GmdeAi^Lv!5wF3LV;SAv)v3J)s$U)u-$v+;X z$`42jQFeh6JwFPex%N5VG}(A39X>!s^>QyHUED_xVLq8KSo3w=4DsevEg?0l5YnTf)#!8fLrBET$EPODhKU_S6PN;jTC~5G%il z7aO|(GSKr{i{?+ztGT_E@G5>0gA0w`J?5%)vmtkET6ChkzR=F01OUe?+j)J1+4%Ik z;4OQ&kNViC!y&fG3V^r7uYRh6Q>J#S&kUx~vWLZIv zX%_OQ+v*_&_J~X!Ml@)@F;9)u+ouz)e>l1=swUWZE9DF%>mF-`OwO#K)=^%f<&G!H z?N?lRm=&6**RqAn+^2X19K7b93o-rSvmDg`cNFRpct7kpW zxYq28`HctO3Hk=q5~%tE8;>HZi3AF z9WEkV0R>761VqaQ2BQnRBT!J6a8>xr$a#RiQ_x|d5&)g`lPE_xzEr$z z!WcbL>%bw}=EmJPeeT6tQIdJn^LO2%{ZNu&%uUXS4*&BQJ(6|Gc#9?0b&Vs!vtEKt z5brB25>hi+?&edTSc8k-V9BV`nd|s4a$fI?>fMF&Ac- zcB+3ppuOML2Ywa523qC;?djR^?zL?WdS33Ac?18HvRY(~uzp%HUGqxX+; z(M;JHqi8vAV~-g7`ne&!)fwKXj-_0>hk8~N&aT;VC7 zz|--)bZQ`5__3_Ca9CtbqIuNcz4S`mC|L~8CjwMsK)0rCEhwHF+}3zb+chy(_h~SB zV^S!AZfja=r?f%jjd^AOH<+dVa6-Uot#mH^?vX_^N+w2O#nWyR&bJDCYUR9m5znrO zQ){OPj087yVkr6T=@wP@kIDNV??!PJ&hosOA(Sje9}L10t={SA6}odG;tLl~y(HxG zgTF~1Tuf1X({t{$8b{*4m6+IK_&Ms881v1=Rm>{Li}+$D9_+d1h51)z&GzxmXsxB^>` zQaGK%`8dy3x(@CuONlZS2{ve${9 zojX@PT1zpX**%L9FV$O>eOCWGuk=HxK}x9ttETuJf2$tjvB$Oks(fyo(cQw@6&99I z^`Jas^{i%;w(=R5u57CkM)re=>yP-ibh{KOW98TW+A!>`Hz0R4{THjN*J=`3Op4ic zb3_9Re2hvZ4nN)5`C@YVydJ!HxV@376cH%|NC`ZALvN1@<=sN%4&oFAmFy>L`ktDG z0LwNjrkYw2;tnwbcxtzx`@IGuW1md1(c8}O`6tSZ95@f+ z%85aE=gHxYR`ie=WhtE#5`oF;R9)4f8hAkW9iMlIJl1&~vhd0P-=U4-*H;#vM zvjD0opjRX<%|WZq-vK{2F4GqF1T=P~)J(aDI@^Vi`+IepITJynQh(vPKkzt#NUS*! zp>R_iJ8=oAA|iFb#jTlg8~GE`9ZG}gjBb>`L4N?van9!{6mNGcpng8(Y0mut*R|KX zu~dp~!z@azvT_Q1Zxw^N=)c+AmMXD+`{-7BM%hB&r8>Y^E(9hev*$;woktNU0<#fy zv7wp?n6c)@+)A&1@UJU62RA$~tjF?&sYo9ff%2>@k3@O8xU7Xj$eifd6FjH^iv54jGgouu$)QSDX~v|+bsxVmX=Xmd{3rh1F3sv`-vGf zM=jWUZ7E4!KbsUXa>>2X40C&3Z}ltBH0NTB_AeHpLk*`mZKqPLlp2fkFz+Pv$a`m0 zX^~$?jhWe5Rd(hnTs~4)J8U~{9%`HUHf|nX7v*&UOX)TDVFG}4D0W6E`F3$BB~);6 z?>5l_A}a#a8DZlnRx=Wlr@8%eUZ^UO{_#I>Ku$SB z$0fhHAHEW@>2Kl~L=Y+VBp2TRPvxKjr~6 zYA{?gznEsH+`XgJ7XDpLuzTR}+m9RMj2ZsnT_w+oApBcBi{G^aPRFrX`1PrRX3yer zO#aGY{U+Hz!~Y}pZQjE-VEfa}h(fF!`K>?fy7d{OR95<#nHZyUd-vHvGv^_%PXq6Y zZVP|iXvKnV?3M~NyXO%!gQo|`Gk)%bIRBEM{%c32mm9NJ8^WJCtA@wjC*Yr-X>PRm z+2k@#Tk#%JY9qaU{5$+f4W9kfj*Q!Fa$EYR!=HIPz{3b@P=8*Qh%=TBp1B9Vqe%;p zBbmB%O#GV~wQ5zn{a(Auf0&9^`^OKzj!g6KUAgCZrR6UsBDqNWxiAAE^W+>=78K;J z$rW{FKEG6@J+l1MSo$V$#+^4*!|4EC*R9K5mm5Cv(cx)Nd{2!&?v&Ar?}(D$ROb7< zjq2B8xp|6r^?_YIK>D>F_f_*LsX800uu>B)#_K8Qd3K&`p4BNy>3G8=fysGZbn5wB zld!92&$6Ic^A39qJP>F z0!t7F>bVEB6zG_$FTN)gnXW2(vlrBblD6#5_QN3Iz233-$9E-?^>TccUp>WR<=5Pj z+=Z-8>FOX;K-OQ4>!he4SSbd*0cT#fnOca+ql9LXBJ6+p%&RvKNkgk7&Xv6_f!PSk zBs5c_kk5dR7J-P*0P~``@O&)ovXV70ycV?Sr;&3IpKrY|g4g|O49FN@wHD}Jo<4p+ zkwJX%_SU$F-W)j1;W|5IKd-a2 zV(hRJG=7Rd*ol$%9E}{ACE-IRCtY+)?f%tqgdPnk?mSQ99L3maehm)Zl=la5%ZdD( zDC0jzZ_jH*<1IfZvP5|LPV9OvA{1)Raqph_R})_!iUOi5PSDA=-iZX%--VDSTnDl_Vt6T}N#gpKSRSxSPc=TXbpw0rg7?J)U%~bSFv3LH$BtJQW%L8rz@i z10ZATx&2%+&lilc;F8b}l=-$^{r8KeYV`Jk9{=3~a^G$lVedWaOXGYTZ~tdAg~IeR zZ1@oO%%dQP!uVv_>}LRP*Sr6G;!j6cQ8snADe(|e|B^C$0b{GG=|5)ruLmR6L;=cS zF1s8D+SK*BB_dm0$GIP;0rL<3H+?z0MYq)@Vbt9+pWQ=b&|jE}=R6nYIojnCYz33? z!d#tBdjV^Zj=ex98+Q&j`)kng&A*H4yV4j79A}S+_P{mjTJrgWPD7ZOa-yY74cG(N z_dc340{Og*nv=1y><%?cp_be(aV8LLhR8poeBbR; zM@PYjWAgqMWz&>p7sR9v46y+t4-_fPKBAE{migBB^%$#Hi@IymhlkmHUnJivd&yX| zc$c);dN)irQ;ZHa_qvW83(5INquinJu4g#fTvnJPWnf`Z|JPK|vK!M_LNZ^isB(^_ zT@4nEEM$wYxo+2RQC}NJi1}E1Yx-Auwykp+Vz5*kfW9FAmg$>!DxV~lrQq!I0)6pO z98-%$Sa2bR(-`VpJd%Sm+>G?}(@@&#WA(K8JX>GF)IE~ZR#_ue+8cTSpr`w(N<6dL3WM7KBeV71LeVBw?hs-eAUo@D%LHJt~~m?K@PUOtcIy| z!mhEZqSaf@}M`l=m+6YG>)nb94-?kg=*^Yo!Q| zd+)7yV9F^erdk&*e0dGg%Fw%@GI%%8pQ@B-^r%0u7~SH^ZV|hRW}qcC{Hx5Zlpg~2JsXY| z&nZ075j5}smeufVec_0}XsKOniqA^SH^D7J_A%36a6XF26RrHM;@SP_=aY+RqE*i} zxjwYUUV?E+g6gtAw;6gh;nyYM?$_|nr0h|ENP-j4igy^wOe6RIRelUQ)X;62*@a6p zq#zU-lzx2rj&_9h*T}js%%B{Bl-&riX$-`i0--{;BOCqb3OKwra)7Q?uSVNgBLdzm zT_Wtgh6ZT-83#(dsIJTVvtJjh7w#o3W#M1t`3v)VfUxZ$XN3oUO-CG1_9{1<(AjQh zw!wXf;O+16I$K3=B-ty)qs3tgDD6;|D3W0Lr%|G~D8QTTzuOB393@%v);lqIyb&{i zc3Eb7I`p1sl|W@B97`Cd&iX8XvIReB!*LG&plFO!YskuPzSNdE_K+1q-Mwh=rfS%v zbu`ZYM61VVzg;&sO$YQX2;}z&Cg=c|mHIo{)7DrfC zH~OyUZv5W;q?@huOq#js{~<`4qY=F90Yo2KpK`ngXbC>36jVJ(tu!?mesuy7`2n=a9xsHapj`E87D$$iQVbSu|F$w@9 zfeDMzJZBU33Z)w(t_n@xPc(IJ+?QNVyTmuPHhsSF+0^wZ6m4G-krvJg$c~=U|E*i1 zG&^i^G6FfU8n&W zubUv=VU4`BsX0Mbd0VCv^ExnvJ9QFOZLiXh>Aq;4aESqvQU^I}boKMOHJW;q_5GLC zpgAM+B!FrpmU7DFSNal4tZR`#1YV{qKO7Ul|Dx_CX!LFfUaNX#&Td@841Ld0k#WAb zIPx68iVh~AXQv%xvG4Jz^y>>%hM5J~k;UZH*MNHE|I)xaG|y^6KXdjF&fpl;>>e0M z`Zd8xN}Kih9^KlZCitS^0-E(j4XM(qGoYN_o*k4>f72}w7kfY1_>@Be#^QRZ$)8zV zS|kEb(vledYyW?wIpt!;Rwf=9$W^j&mV6{uadczSHM+$BZ%0TzB2me(z73&gk|&>X zW~&PrN$)@nNXdzhCE1^roQ$aHs?dU{zQvpwxAZZ6kS3*_LFe1x{Qn`Qwj@|fawIT2 zRn#XfU4!$BgHIa5cIRCKJksm(&2_upQ1uK;r{PWGyFEoA%&li!q!T$g17h;tt@yu~ z@Jffot3X z4EmSaSRw*gHZC1n+Xrbth5NZ1ji)my=Fd|9FE?@;zzp71!7UuRYV^9Rs$T{Ks*ZzD zY$3y82;3LGP17|hE-t2bLs&|ZJ)$PY<23u#gvA|}2xP?{Tb+6s3co~x$kLWEb+^?< zJh@JoCE{PUjhkCPhOzaff+dkmb~Wr6yh`W$s~|gDg|@MRgw?LY>hN-rQ+I9tfauHF zSO;&iy}3J})RGPdeQ(y)!xjiAg}Xu*izZHu@!O8y%Jw`8q5j;0UDV+Ql+Xf<^G4Ff z6Iz#3-j4sRAsm@0-(huj*R5;wMgQK>PvLP(fc<`9toZv{p#+_586dk7}M#vDY;-+Rn?@A{u3(&lmv9X$Mt%NuqnOyJ)kheDk-L9KLYrzbRcD$ zIc<}*W)%PXg4y!ug<3)W2#t={Cu*hVAIhC#oa+1#4a=m~GGj7jXm_8?+vHQ75v z$*YNAzPf!c2a^l)tQYPp!DO(#qFIAyIMIH<*lLoJlb8} z(JLM(#9hHXS#!&KZ_^|pMWnpoA2apTCax2(kKwHD$v@6Mz>p83WEK}Qf#BAXH7Y^r zHgaX4U%mg=sffCJyIH$Kpz-Nv+3&mJd$QAT zDB`dn{=zRLcPAy`$G6j}j+&fz)}1T8r`4*SS;*iME(Zl88ysuad+TkFck^&f5cmsM zn^7U;k>9Sy91N$%TC4Ic2=Qh67pwc~{{8E!i!mceY=BBgTy=(QzS27^ytunW#?VI@ z6>rk(uX*5|8cL zSFd-};0y79{kV{w!pGT58rt9Aj0_`zm4{$F0fg?M$PGPs`B#+srAf$Yf#efv({gN` z0t`=7OQW~nI4GI*(I=@Lpb^hxk>AyL>3s1;yF($(E8T9F){w`Qdln#U&$EHR6!+U{Kbp#?60-54nilEFWh zVYB%unRZ0N6fIPPLm&?mxSvMdtRGa6V+mFI4Sy0grQuz*SARKD(FQMtCuk&hlaEn2 zXZR(|`QY6tgsyPr=5f7MJ- z@qYqh2$l0XtNuswgC%ZU&kW6Ky6}6+@%Mf&Gvc-e(3&IsjIAlo9X$)xv3|o@Uzf`S zHKZV1>87!nl{Y&UPGxt)`c^wG(D{0EcmPUg@!uZ1_I_09+hC6S(&lB`QaLYn5Tt_j z+GM_H>I!6|1;=Z$1N`(OiOi+{#)hF&H zC&PW0%B#!FFDPWp=J}*58!y!brbIshuT<+=Djlhhh~9HiIpOfRE*#&qhzcSjrAqB$ z`r(k5QsdhevQsA`WcKQjCr9Diz6SBVZGOv-*zYfOHzr~cz$SE0ZU7s@B&l0N9zyKB z<{I>)aJy;`j znyg-Z#n;IMr4LI>HgFJOLpSOSmhe}OAKuLl5+>C5xoxBF;WPU`SH*c|RIme^`k*_jwk;X28y4C}B^i`N))Wx0a zYCb4CsEs^M?A-oDn0DLuIMC=dh@0 z3CVc7k8E#@0_bvsls_`d|2V%*&cBWc~jYn;}U3t4<)#bZ8 zPfT#{Cal_NprM-+r>A%piYKh^seF$tw)fh9da5$#sx>K*_0ydaKZ?M3YFK{K)Dv=sSvI7 z;Aef{RxVN#m!KNzPE+qr$eVOTH_^<%+i!Nq!ky|;n~y!6GtB}qP3caQaCHQ?-@&(p zI%%Oc-^M!4`b)g0U)BVU!5p&b0+@jEPE1Cf^yh3A#7jIg^p8RtN)Oa7j(u-$t9M zxaq7W&^w3E)8uhJJ&TmxCj;}%yl-qjZ%$#W>yi)J)_xaYuU^O5KhZAcjF22>Rw|@s zB{3~d;qHO1;aNrz9aqh^K3Ahg1I|L6DmIGtr{!`ZHj3hg+^;gh_aPE8!URfOXhy+n z*h5ZxI5zTzNr%$BWuX`#Fk9ccdu#ig9dimNbKA5Kw!$B;u&m+KQYI5x_8bzwzPHxj zSfI$3eRX%56_>CKmf(dg9qy7qhpZtFL9Iqs7k2H?p@(tJst}_shR6kYe-rb8&MS~} zz#AW%Al$_0!oy>^cOdOMry_F68U9pD($4AB*_gJ@V^M3AjtrE5F4=8f!asiQwmk&0 zwVdkL>e92yeO8h7lF0-;ibb_T~~?jfx;MJ0u8 z=VO#1CEDIbMz9{4#Urfp!KXSY`kBEqfMvDU{%{xO)~oQKWsxK!>flei?ryQ{o}t== z%5M_E$rTx-oYFeyL$TIR&3;F)IX(RAKgqwEI)gT2ob=G6^T6p2~qfry%| zwcTwT>k$DvLwLW8LPiJLq?i%!AofCKvL_uGTbG#@awz2SaeE9gBdJWb9PL|AwCz98 zSfZavfG__s)TqrY(UXu7v%vLaDnekvr))u_79h3&5aPBw1_|(w(o+A&y4Ta&5tX`jz zb!5^AXq4S#sxoR-IG358eg_iN|aZ*H3|p8nxX{qC!HA*I&87 zWw6VpB8Ep1j$bu`naYBu>cr`ni}4{>0}wfY;5VTFeS$2OVN9X9Zh}Ub|0zG1cB|qS z^fqQSoYU9K!EC}I4f@HG^GQu1k2gr2vuTr30_rbA{Uw^MsRMroOBGe># zJwU^JucyR+bl<^Wp6#$Rft$_zvpd{pc!(E)gplR*3G56>j~O4 zz4ow~4Ml}tQ&C;K-vKb!SwwkZ=7(LvE?Oy-Q`RyRn_!$(Gz5v#OwFMICq=XP#!PZ= zd0=_7qs99MnK$MQ1X&usS&SQ;{Yn^bMelv9u?xJ;8A^W$?>q1Hnbb5K8Y|2aN=$9D z+!OrmyaPtZSWG{K{TdrUIXFT*e9asN9$ZPO%=k(&Kj12{1-082nsPO{h8zwIxGKxs z$%MJ-eRPYyo0R4XcqYJ(iK0r1Urzkc>9PSd?j+G#31>_+BDhe8fDr>3^2I9ZpqE~vNK+) zk`|+l3akh9lutc`c@=SxdCQwM`11}S_k8A zw_`UptNBBF{umSYv5DA|jk`%D|>hY~@2ftpL?UCX5BI=X;2ayrourKbXr({DyWByA2`fKUSbg~&rb#CHl zPPAh-RY$|AJMyP%1y(-%rIaUG3VTZB*~+MEY~!w;DL+TiO$!ZxQ8>k2_4j5jriabb z+C`)4)i+J{TjHKThhHk;(Dit@Fu!ojIzWYO5^pZ8ks$K%aeLF<*l6P{O|sH>@}VQ3 zrWPsYWOp0a9pKeEv)_3_ z=rVi-+9>k-F}y4zEB9(Z;gDx@C7`|&cVTTXbW||)+siP;y(+6tg=2LXm}WF$`Xz#p zhx~-$l70%;Kv3WAW-c%<_k!x;-L>!r^5kNiefZ)1xs@70dO_7sB^yVdf#@!k*V*R{}{d~&8zNeWDD<9&PJb=A-2 zT|duMw&GKpEwC>ToQHJfEiJamg7?@w!@=>B`S7f%V>eGi5A2gg(+AOV=0Td3kX+27 zrsqX>y;Fi(Mgml$c9)%3S%IS{O$Rs3h&M1&mCeDie@j{fkUcpf3<1i)hXT&UL}*Fe zGxND8(yqo9Arlz>)QC#xY80fOx!bD*5UxMUTh|Wh`Ga7Q=5<_dXq=@iLO>IfBDyq= zhIbuco=q;%(e~WOT=690vw9=`L#Vb9_!;!sZZ=(*5l292QjFqRh3I1F zBzPR5%m!*+Bx^GT*IA(wrTSS~tYz#zZ^ju`KBH)+s>2PAT=UdBQI1P$l2yW0*e8vg zNh{KxCIcnJZ+&?fGYifc_e$Rsij4#3Ot+*{f!dTDYiI&IC|87evhjwpcyxdY4*a`n zT*y>)(Xvz(Km@fWH<{wWT9}nK3hrm2jA0VE($!8iCIPZ`Ro`zaCAr)3Olf+o$AN=_ot;5mS6;u zzbo&f?2w@Hn212BCeFnV?bA(pt9=t|kHhw-{MtqwLY{}B_j1}E^v{CxRyf$9`CguT zj`SNQYt)(CGJq=o9B?~h`Lrj3BWHQDxFQP~x4N8nNI=uzTN>2B9Q3O)<`uS7#VCu9 z%6+rrFIdGsO3J#z!18$h`3;Ut;|7sMZosshv2b``l$2GIm?|Z6YA7XyQ|xcn^2evA zv2^8DT5PVc5V<_ywmC0WYnicPgsBy*n$GgcMh2gv(Y!kSrAZ&94~wGnozTQTDb+l#=J= z4xZ~Zg8-}#8gIF7CX&@r-Q8ETTP9_sy}uaJ@RkM|WkV5G59p-r;7QtXjIW2I1`>=s zUeXe!0p$)f${-vKi$a_cx9XVdXe>ta3d-02xNsSG4H)b;2 z5?n$~3$}e8I)$L2Ya@pf3mY*(sI`+3WQ~P~HbLWuHuC|#SPi|#BYkwwdy0S82I&4_ zizxy-!7!7<6B_s{j2gp&`Z#3@hdHvW9MRA8^c*g61I&aLl5qxqBQRrEmPQ%I*!)K* zK)-a6na|6XnCEs zE(n5*z|qF=g|W0O=d;4ppJ(vt!zCkZ5k3=F`nq0~SCn`)?H=NGn7xkMa7*RA$u-Qa zBQQz#lF8rPM3%sgXY@0Zy_W%-TDuLjpsRtrVh{okkLUZvQG*D68r5L@hQ=)X(g2{H zrvgT8!26)(%%C)9{s|{QSV*>1gQKNEp;P)uxd_p(R2~rbD!Tg~X?$4BpG{}2LL!U< zTBEIz65XEwv{Z*a`QlI zdA}T}u3O6I*aiNfjL-GUl0rJqK2mzGG-yi5+P|p3EshO&OkDH^HM&0Nn!|OMl9%DT zMLIX9EAH3AtvmsOKuNXZLw_hmoh7C&OH*bnS^--z+Q?0?4(y#6^%zap2dt+bRlG96 zSFI)RXOYJ=)v&vIx&XoB2kq=_f0G;nLq}P3n%C&Q<}4DIqW&e5dmDzPP`5oQgaWCc>pFpRx5&Kt6!h? zM;2Iu0M^HiQYt+|j~lsM3*G*fd+jZ(qDB+QX$lqY!mA;uMG^0~A%^wSf-K%r?Ls4Sie~K(aNqcH)v)2l|uvtbKX%SF1lYfv&NRgLMJn{t0Fjz?7aLgL_UCMIevy6 z2Bn1pb=k0q<%`}u^4DtZEJb!}NpT~U1zVP(vI2YHtgA?^w}?&7Q)RoC`u*ccjl!G? zy6;d;!~XJ>D(mcN)>%aroJ%1x(TI3&a&HK*?_Q;0jN<46dAa5nPevVq-*Sa3yO$Ml z<>Tt>p?BlaIkShQ^RxVDIh8w7JdDH*^QF=8ZmirOB%w=DL2w=a30=_sElx6=DZpg( z=GiO|Nu)qOFlb-ry_3&wsfhiPCTuhPOiNHUF?s&Tt)tn@hE?aqyp~y^*eR!6(58RW za_mQdDh~VZuW)J1UT=2o-yyaMcv@26ly^s~vht5AoGdLZJRGndOnf8trD%}}Ki-;q z6@a#F&9>XGoZ~V_dRk-_qz%+(6w#HtDl%3vc%ks|NSB)7te$ zoA!TL=P|MblHL8z=! zvCMY;4I-*2IHRl5zbh5v8lSQ2HG76_utSoq&qM zrmIMAA|SnY0t7_?MT%6BrXrxydksNQI)oZ}0@4W(S`r{6IS=-C|K4wZYn^q@I)8kJ zzgR2ldG7MeJu~+;*UXp>k*ckC4;n74Xk$iMp3MIx5bgH#c5vP6OpP_D7P1T9u4#69 ztg#1f0wC6eikxR&7Y+3v)$l6tB4v2|NjqL69!qsT%eN%HJSz-&U+L1eu0h+Kxq)&| z+QvgfHL}Q z>F+onvlEI6ZJ6|VnG**mUk_1wB7=gzNu@zjM&KDK)Lu=1w-E} z7&KSMLtTM>IdXfMW!ZN(pCM?Nna(AbA-E~M1#K34LJT{44z1N4rvl0gJy21dFCz_L z__`tE=MSZ$Hi~&SjAkE{E%U~&>31CshF_k3T}C{)7F;HesZ*f5_oN;vGLiQ&8&y=e zAgHJykOrpe!@zi$^f0u+U_mqeoHAe0)MXh_W5Qzu4a!5W#&d!P21#=|4eIXVV+cl% zKziu!g^f`N;LT3b_0QkJq`p?Zs(2SOzS7l<3vm*62Sa^vQb3^e1xtyudHbcZBt+XA zAM-dv!l8$+GFyJiI^BL1UFnE#i|OlV%Z|?G4ZR)H~6)rI-A=;8FT38^)Cw z>*zf#=ib-tBS}vjn55shvAdGy>~e-O@C#}Dm9~@Hcjce=UkVC^I=-@+DtJ%xrkuV* zy=1=YY~K|a`@*7MiYz3#Y+1~|$=_Vdh|O>8xHCoA2X;=b$o!C3WoXIEZ%$d_JTNONT5OIy2cyf(g^9r?+G1{djWijYLYGu zRh`BSFGPtsrFWXwYWt7x#&{KSY-?2HpNBy!cqEj0S^;Ss**@U9wdde-<=}UuN*S-d z^UfNEE+rU?`?RXqM5Y(8X}3NL8`^%;g+8Yu_w3*#fK-83%s=O(0jW_M>)8|I7hUjj zg#^!5wEyN_y_}HeyOWIOF+S-7xWc5vDkl&#gZFlWOjS<5>=p!}(C3DLIIx@L4o_dX z^e7;$RHod0GWUTn%f)*6yOrx0A` zS7TV5AhUys!T?mW6rg-5AWPpYja$T{O=TlnKj=#{)itKCWvEXa=g@D)Dz(TKZnbqw zg_bFMA@vXP0m@dDWr~S-{}^`mQwiE}j9;DACC0%Mo#Xg|+c`KbGxIViYA-?nmGlM6 z9oJ;jD3Z&=L9bZ%L7lv8A$99Z@xpt?U~>pmJ6qI+^7pDaPOoV<A2q}&_ zNYUE`K{q&d!m8zFx-2gs&|U|}HUalJJ=x*Wsgcd-?DF0g2Ybry|HFf1MFkmxM|!zHX?<5dCC0bdpR zF4(AefS$jc1r~JN&2gVlCVgHR5vED6Z5&PBl#4^id&&2+ZpA|0Cz!d1OUo{s$%zKC zyM7nsUVFWJ5!Pox&BYf1USgE&K66Lqd9S#3j&O`Mr<|3sO(oaT7CF!-PAI@Oo08XM z{J^*+wfUD_u`WE|fl{DN{phCpYKL-B)d%sD`p81cJ{G#r-d46Yc-Mhi% z_1_s-KPLZUcEJ34zY*Ftj|9``d@GRjUx{b`W9I+Q&wv*Asso1qNfT@`qMC$yc|@H2 z$QN~}oD7sa`ue`~A5#|L*m;`A_u z-$vcG;w*nc*+aBs?^oNcyP8?pUnw17$_i!|M|@d>50K}Lyu z4!woRM5^a!7-^T++rtKTb8%J8dqeb&n~4D8lv}~G74*L8bimFm%gHt8ST+%}*dT1k zqura7o4*(4cs0}8IjBB0>o)^4GwVdRI{z-_q_B4COhqv7}uSRq~FVvJ~$w0>NJLHLUSk;6*e9-fZSPf zt>MT^TV09M0SG`jFKmv5wG}bi2M+ju!0BKChrO^J~s2ex(?);eA z^Cz|9dUX~{iHmUGlfQHp@K5f*k5ySt6|j&$I-kUZ{*e<99zJ3O)VkO&cqTMn-e^83 zY&lW%XW6~W#=i&9+s>`A&f{eL#SRAkdEoG)GEcGV&{3#v<#Vs5>wiq}vt#~u6>yn# z)o7}4DY4ku;J5gMhri7Kah94JO$GOKC&Z8pbbrpiwEX+W`fO0;@C5$RxVgsSr`gz_ z#r=vO)mYf+eDc@yy*dn}g#H-)Mkf+je8roClP-$L(@d~heMv7|YnVW{+GDc0dA}WV z`j}&PM7Y<&7552Lpk+rL*;qh%x{#G1UgRLXZhEusDrqkRAxZrc5Jlsr8@4u?auAE z#Tw|^BNP(O@~?}ZIp8|5Svfs3(s&Djd*9JxeWAuNm;Q8OFYW(&zrFvax)*3x_!j29 zc?8PuWq4crUOMgbe_x{#D+s!YVsT$sW()e;7*T{MsOemw)M#W8zGe+$!VMn&+Xev- zBZiAQm~3%7aO9TSperFq)G49MG$T3g3OM@vI@CjdthL zSBA5jd;Tjleb62C5fsU=?aF5puYZw4?h*iWe!FAbmD{yAJ22_98=3|r+|TYN7^}B0 zl&}cLrAm(51E~ugf+aPZ?}c`XI(!DxGu^i~gA|Xfa#k&4GvpA8u)cHibwl|@oR{^} z{^iJoodHFK+5}Z^zLWv0GkCED9@|=u?71Z4^wP#Otj`v45D7$qQ51kpdbU5Pw!R51 zz)&EurKzRD<@vvPZICa_sYN|ai;M!w~5ts2Ie4kFg=UCl8XUo<83{Q`qn2{-nAs6?^qB8 z3-v(IZDltuc^j!VB!3PG7c|?oHVolyX`ec_ z^y~cVWscyM{DBNIW2?-|`2&Gsr0gN<#$0f7St_{PJcuyKv6EO??*dQ(>TCC28y3{8 z@LpF$i!zO`I@LPE=a~|hlf?C8{!l?ey?_St{`=r$RGbYdxc61!6%G-j5cA5GqR@u+ zulSJSjl_09A-(Dk?QjP&4pv|21hErET@E7-YEd^R22F7*o>G`lJcYo@E)(35P(_8n zZmcl3uu9kqWRXdROy0FB1()sez=@JgtHQn6zI(RI?>pI&>fAq#2NokQM1^ShWJU$Mx>pbRkRFvteHL-V%0lQqit+8SkE(3>QU)9 z?qjCqID7`~vq^0@s3SC1bYSfTlht*0@-B+>(9>}C4-->-1F$e-e6+!)?YPcJe>#D% z2xR*EXZST*NnJ6S5P`n;%SI8n-H0Yx#x#{onJ{RTv?lsHiHLFgt<>`u#C8_y@T() zA4lg8e| zz}(6^om~O}W!1j0d!;jNLm9#+gxu)u8Tg2&N5$^jX~E0 z1nfXIGGC9cDOvToPzrnJ1x*ix5I_*1*){>KrDsaU~1kmxbR{lX#sIDAMB( z1^>txJAJ=v-{wmW9P5#-D}CDpRw=aG<^&V zH1O&f_TIu}O{m;&xj8>*UA1{eSYH{!UJC#YHhW7R{+Tu;WdyYzjt;Fo#JlLwd1I_IDkz-dG9K^y9BnVK$m78v2Wb+rB ztN{gH9i76C?6tt5f2n9FdJ0f&cJXo zEaoj8>sehJG&}*4di{sg&ifgP6L6>Ac~XMbn$}!e5QGj-1`lYt8IQrx1!Etcc!?CB zR^dvxh`y#FKTzN=*BZwAHi+}K*M8+EdXUlXuBbW z67I<@cbd~Y(6}A~d?H@9WpySn5z+Bf$7bg9TqVrONOV(SgIoyBfK6(Pa)OAPys>`$ zu)wr>rBN?48#0;9T=M>c8yC_kffnv>8dSJQHPWA9usVTldwbYn#@Gigyji#5Ac;-P z&v|Bjx>8|9xSs(cD0%kQ?;O_~T+{nUi%}KCg=^Que947DCwlY&(p9-Yk*sgnI;3z9qmSu)9Ab|l zgLZF%ElS!NVwH^dm&mv#cZ!pD=u{u=Ek(eNkkjhxtdo(|a+@+uFE0X+jjW!t3 z`tbo4cRku}=$t_a?uCw1wK7%h}@JZ>zWpOjto zli_)7FKQ?lfLlQe=+w<7F$L4id{*IY$MQ^^Lc_p28mOtG!A;Z0#u6WQU%qJS9NI!? zs~g@71a~M<4R3x4bbqUXz5m;3`ds`Tu%at5`&M+RsPP%69+Gocc}a}LG)#i~xcF~} zRFJLdO?pn=O1y+IbHV<(j~fe-0;p@$X~_p%hjk?7Ks+&cHuRbjnl{3xy*UsJVBFv_ zeLeP%jDVK*@v(rYJx^y@Hq-?<`kh%2Ha!yD#WVcJ_0-mGUv8}czYMs@t%Q}y%Dbf_ z76z?vB90-w46Kh`R{AX>OHu)et7Y6JEvYwP_wUtetY-|FEj7nGa*@40czjJR-GiL1HZk0GdxxKe~ zc+;g*)Q{xtU%?`!x5U4O_x!d|HKaP7?D16YM(U|qYC|OR9&G+5gV|8WTcxM-yXg}G zI(rr`(q4<3kf8wq=Ip0b7#}y?Ori~r4m=Odv^G;X4mHitmOooua0RHSi0F8w0(dr* z*Jn-*p}OEc{T#{l(i^;AO!e=(wXIb5bOBnSZQ;aBsYCAV`AC1V5rS3u^U>e8 zs9duUzE=@b1$KzAjs6s~q>KVN=Dk4g42_{RAUS{bp;uao*ZeiZ(jBT~F_Krcefz5$ zJu-j-GQ|=Ol2`fVtOjXltT8lcC60^K@MT>TW<=>~7}(V%NGaPz;k0Q^R2#BOZYFWe zJc(C>_Zd&a?Maw2dHoBiL}iFF_4HKdsv=(p5B@9M4b3cY(^GGET;073zy|Sk1=jjLJPh;M^P=}Bejf_m z44X%w%}-3Tk7dAOT&u&}=XMA947V0IH{cUohhovMO0Mw?_c4d&x4qtc%=!m;;39L|P zAqm!3?;NqWg_j6w<#t4KZuB4KZPgRFTPO!oC^vTA(e>SvFZB0^zEzR<1ER_PCd7__ z@M^B*8jiwe*xWsltA}7r$fKPc?zS@gTK9yA5bWs6Ue@%J00aT z@g05Xlp;4V0l%^SLVWM#0lhT*fL|6$v>?h6k>%oTBhM%DHA1f1T zdCDwcMcTzZm~{BSx8A}F6#_V{x>dhd9NgUeU!LpyI$Ug-3=8r)V#`hT>(ACa+mFYh z5ivc##=CU7=m(7a=ZEN*_L$RnfH3D?HO!#R+rs19$6VmtDFvU3see`*1l|xC^%J2k z`~8jW)@PH(+1*Wx~8%xN1 zvdcbAv3$q~3|wxkUu*XMh1S?IyXMpD_5DxcGz{7{ zj$2L8tW~6)|H}{-m=v(NE7w&L{xajoiRm8pE<4=NKl6bEu)YOttgX|)!IVkf>~>x@ za?l;gt-}$k0hjaXqx9ko4y^TNsx*DL$;d7Hmtfr41DAfy{EFEAQDxu+iK6NzGUkDL zKlSZEMTHdWf)1AR<|AM2d0aiMuN;30uTKUhHF4#P+h+Bm9~!Ki*dSO`YRzTs!X zDSuz-YT+|~8*1WC3&AB`iy*%c1d|elaKMqfvwNUE{>NGkcn-mZsJyO(S zXjct>h21r9H3=|VzJkU1u5nJcHoNXPhx_TtX7WWcn=JeD(?9PZ&gVv{UE;a+=pnFk zdS{PYp|(OjYu-4-)>CZ^YijxV)DpGTk~m{(Q^BW z-@aKz!603iDie?S67efR?|*m7>UqDfxFz@ba0LojDb*|VWwG>+;3P!X#>8Uu4&_`@ zSoq*C!SE+~U%1hr&-k~;)^3EwOW)Z$dSuZhb#<_q*lmh_5_3H5Ah>&ICpFIZKhU*^J`z#3I(3J zRYgv{#nl)Fi(CH1mVTEIol*C(eT_Xm5ox!EYiY{Bi}Z9WJDDjn(R6PtPyY=r>7_Mf z{vF0+VCy9AmB(?VHrm}Q6h)?@EV#8}Q8@_cJF zuR7O+kx8}tO<7sl&a3+6*C(f2qLbpsO00n-K6Z)>^*h%rZG3@U;#iRUwE`X~t>zEt zl+)ebB>d@8?=uM| z%(jRER!O+?&UdZ;`tf7mbfR znMnU!JoQ$1n(x6-?s`nGX;7J#kAGiEMd(;gDoO;(29)5`6QRy1_KNQm7iS%2&4}be zuWpOSO(Xg>L+i9xm;`+9{sp3h0R~JcgXMY-b%V2uvpG@vy)$B^Ao0WcrP{)##lYv8 zBUiSnVH{iMlqUX`I;0S|Tb5@ISC9+@91!=7cj5!`R+mn3mkRv#sQ->j9IKBbVZV(R zd%BU<%L=oaw1%ox&@cpMZKEELCRGsMxB?V|EQp)c5?FI~NuKUN~MEB8_|#zn@MxLyQdvF4(FUxXCnjSjf-JMqpH{*-pZ37#?)$#!081jPy3oWjFE zBP?LO7+sK*rNv*bXqt2!BLTUau2#VRKso$F&9w)^O;yLPw;Vw-ryys!nS2b3y;wpJ z%YH%ZkY=~bMO`RopLAboE^~7LESe^wV;G1CH5bZR==(-k&i-#okz`kp*6|Y>m z+px%*JoET9on)ozm>xo+BWp2fsCAI3Ox5BFK@ej7sr*Zi=YDgryX+2!}WtFW^mR9y?Vn#9$N^;{)|+RX$V2!mjlR@w#n!}%S>?TkrK zLTjlzK7y_UyPdNURyppH=trJlBE@X4OQCTT&616D`Sl&>Xt(_4+9;MzG1kM6S|}+G}q&g@7QzuzZ^xkp5Xn*CZ@QZxS0pTJ;E_ zkpn4rG6pA<+92BJx>76;xFiCx8xJTgH21ZQ^<@zGT4|ZgP)#&*IHRM}Mf~eQin4g-L{J_9WFJR{LD=t;C0tcJ5)f>h0fZm=0W| znXt%E!Yk}FU9aXWLc(-bMj!wm%W5Q%NiAE` zZ&jk&b+II%$1Bgui2rYpJpQM{f3cYTRuG>6q!E<^F~6u0oo+D(nX%$qh-C8EyR%+h z%){YMzGm@iK03R-5DPuOC&zQ&-j+E3q-5Rhi4DEYBBMqA)TT>BKl$|tLw4GvIMQ+i z0;`rDa0^IRFTwTN`pM8Vv^lvdji|`Y-j_bB5D8+ZX|bST+7fkjsROV0l4%o+S<|BA7X-Z9vf=M(@nNDouYZz_$?1lT{8aC-M13@HyQl%U@d zl=JRL(yx!5)0bi~>o3w((q}NoVWC8ApN`UeEKx~SrOCwJcCWXWd85=1L9|{4D#e=Y zZah0VpxmE6dMki&J!5>QNC@300?r`pOqIE>ZzT1N`t@Y6CX^nWoWU=;_q)#bqk0gI zsN2I#rr7n;d8;LlLYDT)HGu5%?Z$d{X4-j@eG=apiF=8=z;GP9+rV8hoLdRD(4HtL z?aQ5VwRk^!1C*BvUQAkf23rj+JV{Z>@8qo7?fW8;1%f6P&_>iIe zxP5mDXVtK~M7;KQ9d24_yHsBI+7dqs{O`O?C5ELVpcLAYL=n!^y7>Zmk;1{q$)%cKZ852xH z=7CzDbR8{IgFp1whfZH6RBX(plgBWnk1RJKU~|g+}tRfPp5!> zI-9yG>IWS&N@?D~V))MB7qj)Vz^u{&?9vytCuZUiav(AjaBn2x>oGNB(T^ztpk}^f z95E+jfJR%^(5V*V_@5&pYhY74m7y`IOf{;*aTmf6zNtyp}B31g@3!OLVpO24;|l< zdRkHqz_^O91l4^q5+Zu*F~v)xt1donwhjQDIpEEK9^%#IFzEwMrEePs7FotnCiJ1u z9wDdhwH_*`?*>4#k97iF=l6E@Iq_PtRB<0EmU#nt3{;C))pU;5cBxFoS6W^jVXd5~H8HC2ZvB+r@9v5Lns+*}=S6XfdU%Ig7jnhVLU~~dTFu(27rUanUdWVY zw|~CQH0I_$(HAmB&r`Fv=7n1_ztXlbC}_P7lR6WcQlJ3(ruUI@WMbSq)ykIAMI%piZV#l_ z-#)^Dt0?!!pQA!Tp<^LIE=CMMptPFf<&uZTM0y#JySr;*5y(?WU0$Op0??alz#Mll z8)Yqpa++Zc-KT|bHNTNMxu^W?-Z2eC2Zn90Q^g#yjfhkJ3)vOPJdn4>E(#wv?#PmTv zaGqT1rm<)blw?g|E(a(BE`5r!(P#v%f2SDa`;=ErV7}>p&i<0?Eu^BPuJcRZ$jx!| zw{Ej>a}tm&1UrvWL26>fO_cnQnW+#Z;sa1>_*3V`P@p1L=+1uYS%`kS8BCz^rqYce zRuFNktnI6uOAIZVwj&y7P2h{woWnz`lhBY9jpr3#JoX3z?F>HMFB0UQ{wiU9Z{b@z zq6*M<$`JYjP;B#MfI}awcqmTUp#QW)>KzU+2w7Ayzo`Ia2ar3%3`*{lLy3t|1IGuj zlZ4eEs)6Gi#=-Ew8Z)MH_o3TgAgM3}KhnvyW3gwT#;N>J1Ep;8<|66qqhaddUD0jxITKU*aT9pa!`)IgFZyCsed|TLg{G9k)oVA} zjA#4bN*z1>>jcwN{SXbu0Udo+d_$xLb)Fm}S3*=%3u#ghGP(rcHx*Qa3)^;BQ|@|0 z$YB@Kc1))+p+IP~40cP)Jo?}yMV4|HURh9}q%=9k3Kw!1mCJ%o#!`#`hCH3I;uhpD z%-X>2D-4D3P=F-Hp;m|)o~J>`KE{2lFfEx`;U>dJF$M%tBL&97+mk6*eqz}n>MhH* zf6rV=$?BYJ|25xBt>2MnrsC0QeF)k9yxeT{P^Va1Fpv=^K2IdA-R-?Z*dFn4$Ev$D z&k;WbYHwQDEIk5dbpQ?yE}f+o%xa=lt-suxcR{} z)~+1BHLMw0NTAMXDDajiCk|Wf;&>sxX-eW~K-|9~=?sCU{|1FGhSnGSL}GufC%E_* z$m^+OKJ>pp;=P9f9j(#*pIx2ON;$QDeO;YNiY{692~= z_Pee(1J46=^27fYw3ran`-X}CfBJa$)J!Hx;5Q>tocri^gL?cMZtr|j@ZaJx0Hys~ z;N+h>4y3*OAMtovvujdkt=FsZ1!8!e`@luXP@Q_&T^}_IO^Qrtw8%|L1;!I8xRVYxHp0?V3C>)oADVlfCklA_;^%F=_jM zs_mb#u6?o5iJY%lx#ZscQE$X=`;m;cHKREwVAVCp(XY_7A|L>nnx3Oe(?B9x_nLn3 zd)6I4ujm~;awVBie;Jx}0%UpepMks|VK^Xzfo1vbk_}cgq3uZnVhyjm5d;Uj_=O3A z>QANcFb&nZCS3-b=K}Th&Ckcf*OBL{u{(N(rAvpCD~ojT=F4$}^yHHo#IEapaXbyu z;r}KUA6h+D#BALE!ux6Y-I$Z#eAMaTPlYaDdJlHF$*2Q#2ERzSiE#qTXeHjOV5JQ% ze*Wv2fc_)42c$(D^}g7*@>G_@viKag1v>@i#l~u7(%2)?^^%9=b)2Ibr!R=l)<4NF z*}Plgm<$vizA&<}$1FBoP}?Nt(=n4RFjJkMGm~muFnL&}qWtDu6(&8PQo}AtIo$<( zF~iT=AMY4H(*M@$oJQ#D!2)=tx|v^qx5b1Mn)JM`WIoTc{xAG64nRJLR#42vKf<9yItoXr6GnZF8T;mOGbUr%|o!txrH&Bh|O7pPHEAAo{3QAIk z^1VqPW>aQ9h1sx?yBUK^D+>caCUflL<#$mSuXdY54Ik#+=9t~hrwn_vfFFD(hQ}|0 zyEojdj{KU>e@1(OM45XzrzhUTf^#}2Y`4C8jhBDiuA6KtwZ7(%#3ko-7iC;tw7oka ztfhTlYR!{svUFpvsTb34wUNr|SBS~uB35a#jvEIAb|=;s?O895tlgOMTKOP1z0PL! zNjyCofeXuJeAHLkw_{eD=T|b!PiRKNP8-(^1;}YVhTY9Iht6+0uW{rM77*y21#t8D z89E2Djy`G4;@gM_0Z7nCpN_!X8UU7=IOdrxPbsc_?)%<={@Myin)RvzD$&&Kb5jRYL?3aib&o zTwKy>v~Uh3l|(=3VLWkf*khD=!^9zJ>r95+bAC1Ufcm{9LHNT@_5lsew-GPW1wp~Z zj9BA`mWzQ8Jru-dO4TeIaAGwxHGoQD`y+1uO?!OAnP>w7fInV6!p$+fS&&rIC^mv9 z^b%$RwHzD;N)B!;C?~%N5C(|Wt|*L8l9cTMS4Ykg;AePckwJwgWWr-^6+`Ri5w*TI z)h2H39YIt&z@^$asYKP=dKhUinWN5f*4N(n6m80* zHC8~|!=u$x4(Uj7|G31Hk7VqsK~?p*Bu4l+ZfUu3gIX9A<)pN8Y+TA3yn3uh=P0;N zi8ux*m{z*J(p=rS31gEeFO#BmZsAljuxfK;t&uaNy!iS(|0B=k7Xg!Fc@kBr#=U~2 zOWk|{NK`0OK~nEGi8}xN2Jnpv^4$h~Ek^3%Jxm~DR$6?^X@Z5G7z~?L2lJN(m*!lS zLutT?fqpwOL4b7kVY)3B6_SPwd?<$(mlTY*<$#>A5gyT8WHp&a>aU?eH1xWj?8BAU zha1?U+c$kw3Z>fW2)n6%cQg#Omru6(`=orhsYrXiz_1cEOY1S0rE&AQSU=0a5Ov=HugW~C!Co7?7nFIOdH+jtnB+n zX=*~$S%8UI^sw$07j1nckP&kM{`5K+QEO}ky@Dvv)sptD>@=vlEeRVEF&;ohZj4Vy zw|0q7TopeHbVSiZ1xWi(?2G#NuB%MCgPt%h?4(F&Mv^t<<9$(MQ$l=LQu`xU2=>)i z*c^T)5J9UTfQYBbaKR<+JnDp0-9#0-k>rwUn(j-r1!`Bc3JMptre<%uwuZ2Q1RjmK z!rwZfO6tFi!IRxfAzXdP{!(2Y&kS4u_PSqzb*6mbyaJwn;XWwOYj&=-PPU}o*anis zg;|Xi&ShoAG|jLzT1N1<^Y#`Q{fVuwyPb?4(q0v`>AO=S=NEh_TvcA8ts8rInnQeC+zcc^kL~n&`A*2-FK4VE=;Y)NYBo$H}5Pfe6(ClF61=9 z4}e0MG3o3(NYW~CSvq;W!qnLyfcS8@BC?hOt~H5dAmT@(z$ws!V|QI1*6L4?Ih3vpx17H zQlq{bOGH`>!N@FzCgnkUmlgt%l4GZh@Lp8&%f?i%di#;rtHo|YP@$XS($?9XzT1cW zvPkhdl0d+Oh-mM|)sW9sSKks@j;#Bri5CcafbS4ZAZE+JoT2?Q`2?1czBKl?+c#>3 z?7b5)PUygB7h(JZyT* zxl!DG%bL8;Znep>N&9n|0)6X113y#L|Gb283C9EZ{IfLzg!Ze_fmKButg%s{Yo3mW z8@`0Lo^Y_ecQOwoZGW!~mHoAzUQSHF zgXO*xiRUSOsXN3C;cdr#yqFqov}E7rr^Y_mtJcBL=(lF)!kA<^@WOU1mdM+sGwVj% z4Jq~UW`2yJ?N&+lz$TBQ`v})9xvh&vg4$W?r1a16R!>aSP=h4UU7= zgq@M*(LCU~2y?eZVZx{mPQH<-(kjzBi>6WD^?3xy7SsFbz$34Po*=GdWyY@v9im(Ll!X7}a)qIy zg@GdzBgvzn%z)H#Wm(m6yBlL} zSsBQ~b@Y>M)|eh&aglgPtb0iR>&2mr5kZo564y|CGf>HMeez`zUGVg~?rCOIskYsf z!MKajabDU&FF?`>%bRz({X_)m9H2BEYE+Z2O-iC*0^-!9(q^Da-3oy@U&k6-%^$mm zV(zd=izv2X2T}HTXKkK3!~y|J_EdyA=zw2P%RyVA|8jAix8<`vgR2j|a%(%+fPt?5 z$yBP2C#P1db-pqSyi>8gpH~ImIz$PJyfi2O#e9`!G_v?MmE*O_Yp_>=mpW+13|_7h zw$>{$Z)sItaBLldr+E>HSx|w*WLD*2hPK5AI+~Vhf3@F847x0GsNqTQg`#X~Bk0N7 z2FE1HMq?iynhl)iD)2eap{ahkqL+zNJzD4HweVt5|A0(*i1k3f^zA^USKMkjI*XDI z5+j!Gd>Km~bTu2Fzi!HqGobG3*dAt_HTzMKX_hwXp_vc4SaUVUTr|ZxODf+t)iZsv z+&)^}K9CV%3RI}h!eyWMc6?w`o9VBBq=Pk7`fgAn{bVZPAo?>=rL+CuWB{7&nN?cO zh4({mF5m<_43GEX%!)Mps2reitP0wX&r#ix8y05JiJ1MGq4c$bF2_2(>AeaDurVs`vCrqOlMs6kUW?SHl#0Fli5r# zJPO8cjC_@S>)=_fpEFIcgr&I{#b*x8bq%{xV~FJey}1ot}oZx4&Wg3>UTtLtWhIIv1>D`JG=c0#LXD&+ai zD)V)x^FDCZ04<^TQnW`L(fE#3z(rWg*(mrDSKK{Qr1#@_88@z2LRX)Y$CAg_@tPKm zAx?NpqO)Sd-}^>>KdIG);!&ChbaWce|D-aMg(<5ze7y8~6@hQC50~&Eb6F06oSGN< zCoLk#D3q3~;;UCy|1C_E3no%`^-ZTvH-mkSOb7&MZJYi6p2 zX|dGFu5wVk$3#@ox+;X#ckHC2x*PG4-}I*O80X80N&95YWaTFZv&?JqMO(;8cuoNp z4*B?i`Ws{ByXr?cuPui@{gmy=88ZFCae=nO?}6mAgps7(XoswMg|}4`2|Vcbip#`t z>W&`VXyl!&Lmj0RmksoaxQOEee`n#kh4fea-Uq)g)}dev#oZY1N4~ix1C}IvS8wWt zLrg3m6CDOO2mIbnzv!wzTK7-bws)hGt-sUuQ2>XYO$r1so*QL8Ys z_lg!Tbxw#R5FPJ|nZMRmyf_lp(B~vl9E-TE8<0)gS*c~@)s($OI`dM>FzoFbA9;6i zu&W!5ho~+}92XWWt}9wi8C%xw_&BtPwLFkTT(qojv9e5~)6XR@I<)y4-LZM@&oa2~ z3p;{Qo7z1OQ=!f_ffhTJ&M}y83OkzzpuPr>G2MIQpf3fcg^p3^0~g1_K3_3ShnR?K z@Nc4ckcE8^x3>xq-0;O|q!V#B_YkHuc-`+pUH7=GxjXzwVWq0n5;=4zF-U)X?t%=X zKf{-T+=bolAl@s5n`$V2!84oUxp1C&b`^{!PwmJmddmBAyJ3sGY~eZy`!Y>FCyQvE zMqC)T;)yGR$`c-M4&=w(@Rh?Fr(eQeM z>1d-GrWc>~7AA~vab0Zbm3gJ7+#@fkN(_8T=DbEO7m+;qLV8YQcJ6}>#dKf80ohIMFlon0(ecXs zqNXD*agh|e*^4Q9SI~qfr$5ZAs#Z((7vy(Z`xTB7J};pa^GL!*UF#a@Iej(vcnLt~ zzxnX@KwX z1H+v>44UEDTa>3xA6zN9aI=dOVQ=w1p`JQVVM781$0?}Q0mO5Hd(vyIa~Q9k8pr!) z{A~^+RTY7aLzx6Vs9~?*#` zqw!pXGE1(UK8VY$f-T=Kl``WM?k&Qz!%5ES?ez~*Yo9G0ZaC8TLspJBjNaP@dZ+Q3 z@_w}ic+B5!T>G#*HCwI)pWRJ{vu{3FTSkgK4IL=D{l%&1f}Qkb4wcN%R<(-!SApkW z4JR5*YYuNSJ8Rdi3pfQ1URisPqPab5QYmV&PUp6pM43r)tL^3MJ*LC#ZF!Y;Drx5< z=c}c2vQdkX=hms8-k8>;ogyb*$^PqPeDl+y7rD!B1&^O4>Q4CyhnQpcrn5#{-j&oC zQ6(U&?Ux>y&htrUJBR4Go0DpoN%@$*^h>Mgleq4;WyQkp9H)(T<^4>Xkl^Ca@oSAz z`FyCCIWuNvcg~UO)5-O5Xvjl{tas@GXJ_}aO^uT~j$-O`^*_S&@=0E}=<>>fJWHb! zCOe5ib449DF-7yDFc|9ur>*2 z@I+5LaKV&#lsUQ-1^>Uu`_8bYyJcSxMHCSWNCy=uO7ESBC@8)6BGL&RLJy!Qs5F({ z1*Ai0(wm4R^hgc8Lm;7t5JD(7`0n@YefHVsKKJ|m!Uvu_Ypws9S+my6{N^{kV5J@I z2D>2~fbv`)_V7}h(%cOpQ27pfqwbTM#Xzs-*2%=N^|e%P<8sGE>Eiu>B0n}K30h(w zkJ0vD_5)8(`kH-Z#u551*s2^`+aL>~+BkCs-+DBo5&HT3HM~je zax1YdCHM`k$gKVk-}JoT;phA-;(NTTH2Z;IjdSS&yYt(qo`z^;E2%TpBHOA;u5<}d zfCC3X%i)Hq5ojqESJ%>d?|P_68%=~|`mlHFc!8MH$jJE3+@Av5Rvpjq;jyw;VzcXJ z{n#~k#}l_gR5~Ixy_>6>9k^`EmJ=>i2ZKTr-;?R_IKlS4!4_lP&VX;+i=^ zb6FBTZq##>L!xuOP#qFyM3YnbCE`nl6Alz6p~^?Fk`%PCW8gKH$8WB+SS=<|Gf%fG|I%CkD9Gkr8QUnPk^>ejqW`VQqJYsH)9Q#XSdRRHEk^T0v=CWftq3%IWbi#|Kt`3))U{uFL zme^w>G_R<}gF2a-*POBjtKTKVMkTdzo*iHwwsF0=ySfkC<)5PKm>M=3O*j(9>KIYB zWypKg3cRvor&YrTEzW}4D#v~@-^MUe{y72K+YMLFUlVp0f9wYOOU>Y3&$F_IgcPr| zX8v`Ov$$g8F=;+7w){M~v-*K$CWJIszaUB^pP!sx7DSE&vR17{(+V9Z3v4ZuwsG86 zeAxhhv63HQu$z)^0K8W}_Y9jq3xD)t0~a$CzznHN4K$b_l(uX=*s47|D_>}J%!uSI zgToyW3Lh%rI}^~vb$F6da3^ln4_w2?mrE#`N@-3E+w57FdE80RYFej3Cy%kT#G*kr zPd3N$hNRuBEe&hHmkS+?6M~_I#3H~s-6z6hy1n0fwg6YsZ7;#+sA8V&)Oo3;V^Y;s z8cI)gufP?YXM5ltdwvDCE$xEX$R3p?4YnFofo~?bas5>(hsO#|dnIOh!v$X9tcBI4Tzo``YDpw_-L-ljJV>(6My%n>|gtW?m zM=>s)Q*3>k0yvElv%@?OS%IKY?b_^g1h>0F|yhCZW2 zFxAEQGJE}(Gq+Xyu7+0UGaTXUTe1k41o4f6*6lo#34&ScHs!Ob0bTD5y~+BFhSHJ7 zG>d}aiUWzMA#3O0>lA>HdaEMi0g5=ajz)c*0n6CBzIbVyGy~0^(X1Ynp%~Exxm=>r z_+Xnh1t%Uc5@>L(Wb4`Xuq)9r2b&+rGx1k%5G*R9+r6esnl$d0dT9@QAsCeg+t6Dm zCX9agn(1g90`8VJ*==d~f*$0~okE?k%prCH9yUZ=#u%QkeC@%}jm~AN#DE;6wKLXt zPN~p2W2)t>zH8Wpv6dY#y#{#xDmH0PUi&)cyd2E!J^k$O>jm>38ScI77m-|_35!rF|ZrFYf=7npxy}g>sGJmPs7pqEdex} zE%am-Jlm+OyiG?t+eV2y?%VTk6QJpq)qDuzC=0gD@*-s3F{7llAlw@}y@Q>NjUzgm zQXg871wmt4GoA({%p-J2G4oariy^fBVTytn-2NTmhDq(I!Jbs{N4V%~{8;x_nCYSN z)BVh)+1sTEwVXh;X4edhnT=8|{Hb|RRt(&*1DReL2zs8kO{UPWEUq5|;{S;9FI~oX zdAG*d-sUVX5k3OpPA@lOC$M!@fz>rFFNP1+iP4Eh%K@xG)xcWjmNCXRw2E+pfxp+> zkfEA;B;(0UG$eA_KCy6%3zcgaJ3|OrZ)pn$vfsx~be{!&Q5z!SN$M~YoH@%a4}4lW z0cpQ_l?dx*stbE@XzovY@@sLzW&4u)Z@kVv8~_^UI1o2oyf)<5`T9_gfWY>wL{u@$b)*6~eBjLE^p(MlQ%%riDVJ7n#%^AxXH=uO>Uxaj5|I~bj zMUGayWDs?|X!#tR5gzx&G3FgKszNA_*a+kyo25mSP~N!1t&~x}FE!Ma;p&zyJ697e z1D7;^MuitUOg(aW+{<~qXEvC$xI^jvqi8 zV|G6uGBdpN7Z9&mPg2RL?6=P?nhOEVOUcIkva_@qY4mx7&miz6&|QMrCD=gCQD{da z7kOeU7Y!ekP#+FrLxD663VGh9Jcah@P1~l-9`p19TXr?JH6W~1%wLpPCZuD&1e#GH z-qf@SMZ>Qd!$h^vPu*Ruvsg;uYz8e9fTnmpI>wB%5sdMI{6$VcHGNh{4>+cHQABQ znz^`8X6u1Ijw!|O!Q$5;QXwqewuwRE8qM&-;as>?C;W+u`?YDf!v{iyMHyJuJeqHwAN21+mULo^R#q!|xIK zZ+S)=A$sTVgTEaSQZ&M?uiIg|*pQp!=!=`gOA;+*CCV|mo60x>akJU`?=C+aPVvZmG07?1q8-$nCZGYi#+ukuB ztyPT)9z$Pl2h))s-zzQi#}NC7^AM54|IHU7MJEv(t$hgYw$LoUNIyfIpNcp?ksM{} zsoPJX`y)y%*=Znt_kGFu8ziw0C_+i0xBeLGJ0w8(^s}_u-u#&?n_|-S@;hZQ{e*t> z_CAqzaZDC6b{zec{0rmWX_9hMq8ecn16(FnWu7C^|CC~=!HHe$OZEPnUDu$eqBLp? zBa(kfg}q;N|0wDgN(Hj{-u_n}%E~4S-Zk{2J!}@({vpt+@M5O%06dmRAX}_jx(p*dHM2L9-4_Q)MJVX=T#nNkm>wQY< zZtol0XFQB5SMDt?AfihxhgY8VMqQZanw#Woib?+@P#&}*fIIFa^*;%d+uL>vtk4qQ zYinuL)<~D*GHkutgAy;F!&bJrxk{Y`;uC$=@y+F01`#mVO<8)L5||2ni3mnz$Ca5` zj;|^f40MGwp4@BeTei12keAKi*@#RW1P`7(Ac6GT>@cnW10wZv-g8z4YCuLN4ha|_ zA%Q+>c1w_+oTHOOvTMqhTw^m6$TfuUkdSEoeSC_q*brT|c{tJQT?4wN@QMlQmlCCX2%+Dso~;~N!doKS=930P^~fgA0h{fc z&7kcb;P&=zmOv0;$d9Bn8$w=K{KDVgE8Y&)n3*SO^$4 zColt;(Y!D}sYc%R`EShGHTiuSda0pYa*|LSAEI)v^@kLj)Sj{J;X(id*wdVp>8-&(XmTI9+WD9zP;h8=THbTQ=A>k?x$7%zjiKMv4F( zieJ0zr-qlR1RDC5+E<*0^tSQ?{GtQs&Su!*N7?(Qw+mDP$dwoNOSZRTS~5jZq-9pS zzNahNXEod;W8l%y3BK}$YVu)AzbSC5*}1r{ghq79lD*7;tmI@?Xm=egWV_;f&knp_ z_={Z)oe33_Qm+#V;6ss?_WJY|OEXtP&JtJ@3QKH7znRwyjk6*gCbla29Z^R!zs0YH zimibHnMxR?fpE)B><0M=>I^vxJIOBmw-tt8XE9J?q9+;_YDrmC!*8#jpWH}D@}fF% zWtFF`KkO5rMEpQBC8D?M4}M_i+=pZtvL^{4WTo}5Lrjz+Bn)y8@s&47fYj5JN&Eyw zB9-3E&LO7i{omnn z#LE0;Kg@x9(j(-`CL8T4k)w~~oD}YHL$WN zGD)2X%S;0F&e=p86-(Vqy8R|9jp5&QLA$4*boEa8mCewY$zC&5FkEtA6% zu_Q*Lpj#w}b83UX)%CxyP=8TZ{K*gy0kdc6##DAZ+8vx3T&b3Wh#6bEB3oMEq`NUc z$rx+1^s*-qsc`1TvUeC4S8!sFc9KLTx&(vb*uHX-y+ou4xa|a94EYV}J8McLa-J@) zNp(Q5*GO4h2xzvA4+)V6bwfm2)(ZiM&$l^<2(`xEpFQgTa)kcFngaBdfFz|Iv~VJT znr+N!oC!NVirh!t=sw~#1?QKU2E$(Go}StgyGMGt=V~FY`m>igHab5eGr-}S8c+EM zjmMj#vrR{nv1}HLxSh?T{iwMPiAN<$3+^gKS1A^l}a8oInV)HsqGXXSfSc8;l~R}0+tW2lgV8@rWvPlvr|fVqJW1rw8ZLlM9^N zO#%_?DKE@R|BcD}50oWDJq;pOB`)ym$6RM%=`W88Cz1R>o_{nww_-Y}8Zc0NluBO4 zXs5JNgDVej9`t%$lYZbgI@>xqY%uuSC~SpzhZ#^f0Av<5&D;Y6hkoeb=%#xE{6^P zQuk=iu({`dzr6lS8h;U_5RutC3%d3vEJLhW1{KT2Erzt49E`+8?~~Abd~+~Q`h%bP z4;X2dFC>ybQ|%@^4*g1-pO8dJivCN~@!w&gOu|Igvihr}f{VW${_tG?pxn<4CD_EkpYu}Vu*4;mjLy$1S|jH4P407y z(hZ5EFYEsuWO1Gh7d#}A?HZmY8KEipV=S=g=mt0?YH&?xyK%5f%PrDVlU^1hTg!~d z88K!qS~d5z+V}|u`mLCdhc2A6w$$Dun_o+5ADrtUHlKfGTXjrqISYstqxxs!Z!}IWsEY%P9uq*;hkbX<6u)*=h47* zEz_UHGzMsf;*HV6lr{5Z*%03wMY~K zF^8kle`XI9)pBz=|8Oj;X-o+p=#Fx+|6lTRVm_B2_dncIVvC6LdVuq=7ZWJsj;LX=NaeKtnI{y{qQcHCjMVNEP>m!{ySR^^{6IWPmGRnb)A4g{uvRwx1gSd zYsHwX1yZ))Q^i#b_fstoZu%2jN(LtMCEqFy85mm(SVE_BN@%9>z_&eWc`7$0G((msWFM79@kg20yNSh^ z^^yq2|5YRM7dz1(#C8_lvJqM*MOcbLcpE5X70+-@vx{dEeK<>JGYl&@&g>%i)^zj0 zc@xCUJ3Y;T$bhNQ2i1l(s`fbJ_4P@Pa#^XV5SLkk28Ed-$+1~v-8ncFIab%3h-+TK zT^tSr&GL!dagA5s2K5j&H>+0hhBm5_Ep6vG(cYN@VoRywcfwK)>hGx@T;m_3Ghz-L zi>y&&W{I&YJ?Z=rP?`AQHTESRH5t0ogmY1gLW{=${Bz+p$^V3u6xb1n;8L&D<9T8g zpos0kQLg8}BMI)UFa8f-yR@HUy7xpI(0Pzw-{mLvzSYh6)^(k()fAJx+^(5Q>PejS zo7e~4nQ3#XmD(o2Icu*}zJA-@NvxZ-h7%WIoUz><<*~GEuNq4~%s5=P#m2Q1{0Aze z6xZuR^B^_OtDl^+Qpj-T;*Y7h{vEnFQp{%K zbRz&EQnmip+-^tq5qyqiKWAo$g>A24o}k*Yna0OMU7()!5FWyOYOY8k+kx7gK7Dc| z4c5FQmz1^6o8sfzD>B>cwUV%Ph<+b^mng0z!$0EcOSbAz4+vEvnJ&CenJYyS!zjcg znCx9f2Tb8uWhS|tZNGFW?ghHtB-0i`Do8v~$rpbJ8dRW$3%?VgG8?|p?RByWB(jcJ z`VSqCC_=+3+}#1&)K?aK=`PGm20zvyk>&m$YFiR4SWLR}(|mPb0jF0Wi+jA2K9k1g z_Xip;chb3T&KK)9oY)h%CHuMiM_o9{_@lH2jk&MLs*q{5Fnh`=43Wr@7^$|jfMqHi zI$V;a8h&r&aQMDYV!4pGY@uH9o~UCI$*X26Pi_I0osP90^$$kXw1sVM<((x1!OzQl zK_&uY!j};{@|hhT6a(6RW~1qIWTEj_yoDM+Mz%#H2IOF|UON7M=EhC-7&t&==cH&u$CPg8;Isy8hf9_DW)cWla8J z{$v>x2lMdd;LOzE?soQ~x`n zR;dwrefx{y9r^nbXs`DLeDM+;vvtwTBy-rI;IoF#yn}8ju3t*dG*<4Ft<5oV9rN?Z zGj4#YD82Yo_MEw|H{H0Y81*qg*>iac!PJPbOKuMficqFIL}1j^UA0~-ijE50MpPY! zQr?`X+pF`baJgRqKxJU?{^_SV!egRdGdX*eRA0&cDpwBump$2?D7#vHrQ_!Wi&a>l ziPo(|9>i}}^6vi4&J}|v6XPyFZ8SSQjt%J zFG93o_rt-w@h{^JAw$`V`fb&jJ}bGzgiW3{#s|?KG1ejG^AW?h^+Mh4K~Wy5>~1^*}w7Y$l7FhC+>b>f?aD%_Wcy zpRc^)(iAODYVU>%UAftG9=lfh-VA~Sz6N&AN| z{>fUEt*LCHVTOw}gsfIRnzp>PqB|?%SyY`rfh^5NmAdW8r`5W2dmdE2-|7^a@w&k} zyezdJtJ>Z0D5R};(?UPrECnbf8L=`)w<(=i$aX4gk@CcRc<;cz?gt32HdPk|=s$3+fT%daT3%J{AYBB3! z@wLgT1Vem~F*5gkjex$ZDY*goV_GxYsL$L-$jVTlv83f<qZ_oiMa$qai)v2Bf1AcBxlG#x5_h;HMYc7;G{4+h}z~a9+G>d9FcA)X(w7J(b$w zvnaNpR_a8S6r%{H8^s(5PtT?}rQXO^8G6D?3!H6NGS@inmv7Q?a57Bzn>+QDGoKeJ zc5{k6lGK-eE*aVXNUdcN?+gs$!06XG7n1+`nRTkxoDHiQv)L$fB!R_}~w zC-z*LnLOp+!hgMw=K5o_4bhZmrZ}!PilksXb?YHlPXm?xyQ&4cy`OXeP515v%$#^y zG+qbJ?ugAT2LD3x4ItaL`nI>*rpCWUU#whVqPl983xx+m%HK_uwM4eKP>-e6vJ}@) z6Z;y|b}psMYOWLS@V?}QgURT;Vz11rFd5le{VdIbbP+d42Dr*VK>?V>uUrb0s|B4i zEGQlB(odJDWLc2nN!KJ|6w8ZVrtP1do<2yjAGrh!B+EU)@EXFN3}0a+;hd4|c1zx2 z;@Lk7UV83GW(ad`(&i}BW-n>~k(E!F7yXq?C1G1}fEbaC_^i+}PZfvnb=>uA&E zD=OFpa!6(!9Pu>S)08t|GOdh=23)lUvYXQ$T+-Rd+!m8@oo(EJgR%vX-u-gcIy$y>d?uc*i21$}x^eGclA7L*k+h>~F)k0{Y7|o!;S=Mi5a) zDY6k9D^V`hDCbIubUD|ye(PDt!D$V$3MG$G0w}1SlK6i%JX!p#@=?5L#o$|^wsO<( z;GK0@&m(QvmUolmHdQ?9t<+jaiTCvmeck2>FJV8(ncOGh+kahx3dOiYNnLclu;R%; zCO%J7-GHz8JrGN~?e)x-a?)9$PXCkIEKO1dOmv`0CP|VAehljH^YBN1w{TSmv zAdScP>J94Q9Y&f1m+;h>U*%cmfs04Rc|gl=eW?>X!{Hld2dlwaxHl-#D7lY(c-~Cv zyXL~>8$oJg-e`PJ!flB`DDub2qD1kP75lPQa~4J?x)>EI=#NL zY3PktO~DnD#j>IIqzbnh!C8|bUHSf)ipKSykW%Up9rF;F0=AEc7 zOtGqCwE~SB_r=X?z0?v6CQ~FdNetY>t8Z2>tuPeUK8!2!Vl+*ueTJ8SJ6QyGk5co_=ZPDS-mztpdzeAZ<}VQ&3)VKeyCZ0^Og9;Y4Rt%t1hm$p<0uI zf@$o7cCaq0Yos-F#e(7W0N@E5EMIp^mI){5qY5KWIV|m5`0B6VpZ^H{!U(xx@@3mg z8#33ATnXMq`gqDFm&{B4mi>DCwdzEaIT9U(`10&msdlBMOqpI^;?eN!t&YN2VSf&! zcz(xH+yGx3{{VHA<**o!$kt%PDSdAnp(@wAo=ThHVAB4ycGs40FB6tOT~Bq8-l{n{ zc_V4Gpcnd-6Rc4702Yna4u~h^wPZTMY|rNNZ}x8NHO@O>v0N>pZp^y48SfhD^70VF z@<@mQV%lG_2=J`zP1h?0>hjjUFt>ufFpu?iDSxdxYC=sk#Xd+{4(}eA? z_Cr}FSdd2)QTe612CCIePeg05_1M%QaSgl_4HD64knN!wZ+bgdI&HVswnr$*%{y3k z=8e~e-$k(Wa>Ue)GO}ow_q`@>O$HJ26%XAYZ8MegjSl65#@2a089qpvXZVYV>8_|E zdLu}y|LxLE)}Jqj?WUwcd&Q8jaN|~2mfFouQI-X;c1l3jOD$Qds>&(HS&(Y{!0`U` z^ig7;#EEZ_MNu(O*RFq`w)90#xEHigBQPkznkz}uDJpe*52+mBnhL!IU-?3M^#%HN z9N!eXF~P1L$wohTnyk|x!W@}pp9-^jqLyMMcjOU?x`m*VkA3$2+r8@7*QSb|ktOF8 zKJGfE#XEkgRMe)?zirIBwjh@1pPUpylItG#a@;I*k8LE4?O;j$vTk^Yg;{}-qKRqS zBGf!y$&Ea@pY;30OL1x)tgX1KPHkO#656f8Q7Yn(Eop3jHA(CCIFIQCJ5;3L^HR!K zy9~USXIf8Ks1)-!t*;jF#nU`kAtYNJ7|5Fxt6P~h8P7F6BE&@D>h;qZa*;{?B;4Rz zU;bmq4ieThD-ntsx~tLIv@z7o@EkK)N7|k%OTC7@>Gb92W<*6I8Qkfm#?zFzOlUTW z>8H-LN1EtFNQqH%0}7o1E3xgTTcY4TlLjm>XFP+bdfZIPI`(By&`fu2^&fd}BARMz zie{g(QNGg$j8E#PPCSOO!37by= z&@?JLYcjXY{mrW=gYj?9u3^K!&-lQSN|-l$*YsxMg-&SF1QnS5)_ayFSmXH46Df~oDyNj&OJV}taJ`j=t5fObsw!UDS{nQS2~96+v4~aDmCFg61;>?U zQR-~fVITctM~ElB8nx8n7C03!9iZ;WRB(VcN1KcayXJY|@-Tb7@tALrLA*MMa^MO= z&g=9Oo2%l8;Xlu=P5kmT#3IO}RDr=V@N(Fr0RV7K(ktJI{QF4%Y*^@?>P0XGp+7!D zY|S}q>{@eakTcD^ zZ2WBEgfOSUxioE2@pCrqu;J)$ee_SABD>WrI(M%PAKI=7$2IzdC?jD^qZ$esVbbH3 zzOXm`@dL0_HGG+e;m2rqU9RbkYZ7i=OxbzruLof&OacsAf!SKuj28L_f|{51H5xE` zc-tk(FCR3g$-n)%_+bL+unAE0h%!DnBC83X!NR4e z^94X00*gk_$ZGhs2CjQ9-J!&Rq%}Cr^X61{SGuFJE%W0MCsgH;+A|w9kaAP^n9a*m z2#*X^pmLU_HPd1hN(EM!Z?IoOokG@twsf_&ylqin`o6s7P&z{>DE&i110-SuW!L-I zh5yzn@Ti*C!B3AWbr&o%C8cUsm%c9>-{7<;n*wkED^_8e z^MbbPDITmY7MxyEB5=<&42P>aerfC~wM^_3(wvx7Oqi)rDEFmWk4z5emRz%sw=wVO zgAG+f*Q{%=wQY>Gu95mj<*gi9!CDH{Sav{f)JTP$3+_<8{Frm$9>#FFKmj^{T7Mg` zJKl?OFeooU%sxeG)6{T(?tH^)aT!ECR6`}YU0tgVKZpRI{08rG%yh^G@3;nXyG_(9 zI@%~Mi-L;Xnj6$_g~ScjK6Egwz~5Y@l6Y9+;=Uq&U~XAp(i(Pdv9Io%-)(k`bG=#@ zWnYk=?92@Rre=!Zmp_i?7D==sd^?rS0NkmK$}a0TJiuRK@;<1Sv4c}Dm05MD_VSdB zMHu-1RL}TAx*>i&oT}Ukq8 zT<=q6)aL_=M!%k%sbz&#I#^3I<}VMe`(cI~lKCK{4IbZZFJnO~Zynhte6P@3H}gwp zOMVJihD7dy_|{ZUQe?O`()@UbjA9_U27E5hVc9vYTQxzKYjlL!hOHUMatnN9f0-@i z0*SENBfC4Lxgyl5>Y+L_;e-ew1YtpTI)p6W+2Qx=gZrLm!={;Ijd@@FP@|oT-sr@* z6zZl%q=PC_aKGS~v3D2`PeAhZ6hr5{b+(Q6<4HgNy z5p0BG&G&MI$!|2NfB)IhI??sMhiZt}?QcO8Jj)H>lDgxTj}EAF(IH+ z9DUFrrNPypbaAn8*n(bQ9KaFb8A1UZnvuM=Elo{;%@{12D>uNOtV!e;Pdlln7@}t_rL7O;lKNXtH}u zDg0l?u0&}3h%j>UdLSey5S5D^p{cCw5p=Dr=j7GE9Pklnfh?~Q$#?9WK8|ywQI=mR z+Y4s$Q$RaUnbo#Upd7!2ipi=q0> zCL6DX#v18GGtRfXxBuM*Wcip=nA)|ta35R_nYs-_C~r;6_o%;yT>0RYa-(YWKkpgE zy|*`>{NqpB^?$!2uRqh)Q~&1=-rlHM|Nm>4PyI{LTdecrK&}xl0X9Rp4$nOXN`~7E zOjWb)r~Lv0bmx1=d*MIo(D|-bNgW?$_x+KkC>`;z%|kpUPF9L9f&_E+VEN)afCSbV$nc zaaJ$=$NTGi+0Nua1b4y*H?jZc-@{2e-kP{{Cx6C_&JBj6||lj(iMsfNE1UTgA$|GZr8Ksd%WQ_-XZp$OHJVv{h;{6)m%C699yr^5U?RSbcTK>(s--_yrQl1V z|9o%QH)|9&5j(bO<;tP*JGeJ*?XP;FYG+od=0yhD)K7@;JY8Tmax}W2foT|^9T*Zd z#H(rJzZUU@wxz*!?xo`d1#spE>MLn8P5%3qgxR-DmH5F|Boa6Tr^}5`v_ByoqM;H> zf9-R*qwzDc@!XYGuXo$}PB>H1P@#<^G26rj=|u*Iz#$(vFmszTfIQ2+-wfX{SwUA_ zgr*{zjIklAd0fzr8Ma*hVEx_mJtbQmno<6L7%qk~>pA_TOk4H-So8dW$}@RnZ-mDY z-)*XwPHF2q5+j$IT(x3bAB3=JC9N^3lx{(6#36!IkBmlITbr(Oc2)(;f$DQ9& znPo)=G&dqXhSk&xOe{5T2J)QjNbIh{9>Mh&1<_Fe>hGRQV{WUG?<$=aWinJ=$C${6tu&TRRUJx<9d*wAYqUISbWo;zOTAxpTec8#RwyP3@M#L*eNL!4I&uwE zD*#W(*wN5`OA0Y$8O_SlQf50-1`X>Q7J3a-yB&NSXix(mPX>-s$G-D##*cNNRFdp| z89r`1*zZ8qwiuR}BLi)N4)52X_oha`@N|lyaQ{thLRPT3oDabQG%Iyb?R8M7ITLKu zLZ7ZH5gIEWP~PZ?vqkk)o69$d>j29;EcNYAGr?VwD|(>StWyYhzT&8bx=;kLuY9l_ zH{z%&{p4eB^&*`n6`X>f)%TZu)pnbm;DaOZt0>*%6R3(6W{HOu721}a)UBUfh4hW>k>vJ4}3FnYn3FvmEL zQ0w(>H&`-#<*w9nLQEDUt?xDWT*@okKFJ3zF{pglSM;`g#(s+gF})f+l^UCbM}|G* zF=umOIXYM!n(!I-w!8LgWAEtkWR}nm?-OhT=b4Voo)>IPjK5A1!Np`)yCvfM@qYEM z^(i`Ee~aTEJ7Xou8M9Mm+3hK7q00Na$koUXo$|8)@7#a~l3baFeytDODmw5(sr(s+ z?gLz26Av>jU0iOcOIdmXiG@eW%0APCqfW0r7-Xg9yEysfPQ<%=2h(D=3NWFVxm%V? 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 literal 0 HcmV?d00001 diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/_index.md new file mode 100644 index 000000000..dcf52cb72 --- /dev/null +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/_index.md @@ -0,0 +1,142 @@ ++++ +title = "WebLogic logging exporter" +weight = 2 +pre = "b. " +description = "Use the WebLogic Logging Exporter to publish the WebLogic Server logs to Elasticsearch." ++++ + +The WebLogic Logging Exporter adds a log event handler to WebLogic Server which enables WebLogic Server to push the logs to Elasticsearch in Kubernetes by using the Elasticsearch REST API. For more details, see to the [WebLogic Logging Exporter](https://github.com/oracle/weblogic-logging-exporter) project. + +This sample shows you how to publish WebLogic Server logs to Elasticsearch and view them in Kibana. For publishing operator logs, see this [sample](https://oracle.github.io/weblogic-kubernetes-operator/samples/simple/elastic-stack/operator/). + +#### Prerequisites + +This document assumes that you have already set up Elasticsearch and Kibana for logs collection. If you have not, please see this [document](https://github.com/oracle/weblogic-kubernetes-operator/tree/master/kubernetes/samples/scripts/elasticsearch-and-kibana). + +--- + +#### Download the WebLogic Logging Exporter binaries + +The pre-built binaries are available on the WebLogic Logging Exporter [Releases](https://github.com/oracle/weblogic-logging-exporter/releases) page. + +Download: + +* [weblogic-logging-exporter-1.0.0.jar](https://github.com/oracle/weblogic-logging-exporter/releases/download/v1.0.0/weblogic-logging-exporter-1.0.0.jar) from the release page +* [snakeyaml-1.25.jar](https://repo1.maven.org/maven2/org/yaml/snakeyaml/1.25/snakeyaml-1.25.jar) from Maven Central + +{{% notice note %}} These identifiers are used in the sample commands. +* `wcpns`: WebCenter Portal domain namespace +* `wcp-domain`: `domainUID` +* `wcp-domain-adminserver`: Administration Server pod name +{{% /notice %}} + +#### Copy the JAR Files to the WebLogic Domain Home + +Copy the `weblogic-logging-exporter-1.0.0.jar` and `snakeyaml-1.25.jar` files to the domain home directory in the Administration Server pod. + +```bash +$ kubectl cp /: + +``` + +```bash +$ kubectl cp snakeyaml-1.25.jar wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/ + +$ kubectl cp weblogic-logging-exporter-1.0.0.jar wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/ +``` + +#### Add a Startup Class to the Domain Configuration + +1. In the WebLogic Server Administration Console, in the left navigation pane, expand **Environment**, and then select **Startup and Shutdown Classes**. + +1. Add a new startup class. You may choose any descriptive name, however, the class name must be `weblogic.logging.exporter.Startup`. + + ![WLE-Startup-Shutdown-Class](wle-startup-shutdown-class.png) + +1. Target the startup class to each server from which you want to export logs. + + ![WLE-Startup-Shutdown-Class-Targets](WebLogic-Logging-Exporter_target-startup-class.png) + +1. In your config.xml file located at, `/u01/oracle/user_projects/domains/wcp-domain/config/config.xml` the newly added startup-class must exist as shown below: + ```bash + $ kubectl exec -it wcp-domain-adminserver -n wcpns cat /u01/oracle/user_projects/domains/wcp-domain/config/config.xml + ``` + ``` + + weblogic-logging-exporter + AdminServer,wcp_cluster + weblogic.logging.exporter.Startup + + ``` + +#### Update the WebLogic Server `CLASSPATH` + +1. Copy the `setDomainEnv.sh` file from the pod to a local folder: +```bash +$ kubectl cp wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/bin/setDomainEnv.sh $PWD/setDomainEnv.sh +tar: Removing leading `/' from member names +``` + +Ignore exception: `tar: Removing leading '/' from member names` + +1. Update the server class path in `setDomainEnv.sh`: + ```bash +CLASSPATH=/u01/oracle/user_projects/domains/wcp-domain/weblogic-logging-exporter-1.0.0.jar:/u01/oracle/user_projects/domains/wcp-domain/snakeyaml-1.25.jar:${CLASSPATH} +export CLASSPATH +``` + +1. Copy back the modified `setDomainEnv.sh` file to the pod: +```bash +$ kubectl cp setDomainEnv.sh wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/bin/setDomainEnv.sh +``` + +#### Create a Configuration File for the WebLogic Logging Exporter + +1. Specify the Elasticsearch server host and port number in the file: `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml` + + Example: + ``` + weblogicLoggingIndexName: wls + publishHost: elasticsearch.default.svc.cluster.local + publishPort: 9300 + domainUID: wcp-domain + weblogicLoggingExporterEnabled: true + weblogicLoggingExporterSeverity: TRACE + weblogicLoggingExporterBulkSize: 1 + ``` + +2. Copy the `WebLogicLoggingExporter.yaml` file to the domain home directory in the WebLogic Administration Server pod: +```bash +$ kubectl cp <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/config/ +``` + +#### Edit the WebCenter Portal ingress (Only for Voyager Loadbalancer) + +By default, paths for wls-exporter are commented in the ingress template. In order to expose the wls-exporter end-point externally, you must edit the WebCenter Portal ingress reapply them if necessary. (See `Using Voyager Loadbalacer`) + + +#### Restart the Servers in the Domain + +To restart the servers, stop and then start them using the following commands: + +To stop the servers: +```bash +$ kubectl patch domain wcp-domain -n wcpns --type='json' -p='[{"op": "replace", "path": "/spec/serverStartPolicy", "value": "NEVER" }]' +``` + +To start the servers: +```bash +$ kubectl patch domain wcp-domain -n wcpns --type='json' -p='[{"op": "replace", "path": "/spec/serverStartPolicy", "value": "IF_NEEDED" }]' +``` + +After all the servers are restarted, see their server logs to check that the `weblogic-logging-exporter` class is called, as shown below: +``` +======================= WebLogic Logging Exporter Startup class called +Reading configuration from file name: /u01/oracle/user_projects/domains/wcp-domain/config/WebLogicLoggingExporter.yaml +Config{weblogicLoggingIndexName='wls', publishHost='domain.host.com', publishPort=9200, weblogicLoggingExporterSeverity='Notice', weblogicLoggingExporterBulkSize='2', enabled=true, weblogicLoggingExporterFilters=FilterConfig{expression='NOT(MSGID = 'BEA-000449')', servers=[]}], domainUID='wcp-domain'} +``` + +#### Create an Index Pattern in Kibana +Create an index pattern `wls*` in Kibana by navigating to the dashboard through the Management option. After the servers are started, the log data is displayed on the Kibana dashboard: + +![WLE-Kibana-Dashboard](wcp-kibana-dashboard.png) diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/wcp-kibana-dashboard.png b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/wcp-kibana-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..fe55d268099f12fc219ba7e0a920aa8f14439d61 GIT binary patch literal 133313 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. " +--- + +### Recent changes + + +| Date | Version | Change +| --- | --- | --- | +| 2021-06-25 | 21.2.3 | Only Oracle Portal 12.2.1.4 is supported and certified with the WebLogic Kubernetes operator version 3.1.1. \ No newline at end of file From f3391288cdcbe07a816cb5864252d2fb16235e58 Mon Sep 17 00:00:00 2001 From: Anand Sirasagi Date: Thu, 27 May 2021 12:14:18 +0530 Subject: [PATCH 2/8] Oracle WebCenter Portal 12.2.1.4.0 on Kubernetes Signed-off-by: Anand Sirasagi --- .../installguide/prepare-your-environment/_index.md | 2 +- docs-source/content/wcportal-domains/release-notes.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md b/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md index 9577ed9aa..cf88a9785 100644 --- a/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md +++ b/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md @@ -99,7 +99,7 @@ Oracle WebCenter Portal domain deployment on Kubernetes leverages the WebLogic K 1. Download the WebCenter Portal Kubernetes deployment scripts from this [repository](https://github.com/oracle/fmw-kubernetes.git) and copy them in to WebLogic operator samples location. ```bash - $ git clone https://github.com/oracle/fmw-kubernetes.git --branch release/21.2.3 + $ git clone https://github.com/oracle/fmw-kubernetes.git --branch release/21.2.2 $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/create-wcp-domain ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/ingress-per-domain ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ diff --git a/docs-source/content/wcportal-domains/release-notes.md b/docs-source/content/wcportal-domains/release-notes.md index 4a2200482..7bd9eecb6 100644 --- a/docs-source/content/wcportal-domains/release-notes.md +++ b/docs-source/content/wcportal-domains/release-notes.md @@ -9,4 +9,6 @@ pre: "1. " | Date | Version | Change | --- | --- | --- | -| 2021-06-25 | 21.2.3 | Only Oracle Portal 12.2.1.4 is supported and certified with the WebLogic Kubernetes operator version 3.1.1. \ No newline at end of file +| May 27, 2021 | 21.2.2 | Only Oracle Portal 12.2.1.4 is supported and certified with the WebLogic Kubernetes operator version 3.1.1. + +>Note: This is a preview release. \ No newline at end of file From 8ab627dafb7e0085aa359d6cb89c16a814171dfb Mon Sep 17 00:00:00 2001 From: Anand Sirasagi Date: Fri, 28 May 2021 11:14:35 +0530 Subject: [PATCH 3/8] Oracle WebCenter Portal 12.2.1.4.0 on Kubernetes Signed-off-by: Anand Sirasagi --- docs-source/content/wcportal-domains/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-source/content/wcportal-domains/_index.md b/docs-source/content/wcportal-domains/_index.md index a412f1840..90b27204b 100644 --- a/docs-source/content/wcportal-domains/_index.md +++ b/docs-source/content/wcportal-domains/_index.md @@ -19,9 +19,9 @@ The operator has several key features to assist you with deploying and managing * Scale Oracle WebCenter Portal domain by starting and stopping Managed Servers on demand, or by integrating with a REST API. * Publish operator and WebLogic Server logs to Elasticsearch and interact with them in Kibana. * Monitor the Oracle WebCenter Portal instance using Prometheus and Grafana. -#### Current production release +#### Current release -The current production release for the Oracle WebCenter Portal domain deployment on Kubernetes is [21.2.1](https://github.com/oracle/fmw-kubernetes/releases). This release uses the WebLogic Kubernetes Operator version [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/releases). +The current preview release for the Oracle WebCenter Portal domain deployment on Kubernetes is [21.2.1](https://github.com/oracle/fmw-kubernetes/releases). This release uses the WebLogic Kubernetes Operator version [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/releases). #### Recent changes and known issues From 4a575042668c87e46e5ede7331dcd3a809382a0d Mon Sep 17 00:00:00 2001 From: Anand Sirasagi Date: Fri, 28 May 2021 18:41:05 +0530 Subject: [PATCH 4/8] Oracle WebCenter Portal 12.2.1.4.0 on Kubernetes updating version Signed-off-by: Anand Sirasagi --- docs-source/content/wcportal-domains/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-source/content/wcportal-domains/_index.md b/docs-source/content/wcportal-domains/_index.md index 90b27204b..c55eca167 100644 --- a/docs-source/content/wcportal-domains/_index.md +++ b/docs-source/content/wcportal-domains/_index.md @@ -21,7 +21,7 @@ The operator has several key features to assist you with deploying and managing * Monitor the Oracle WebCenter Portal instance using Prometheus and Grafana. #### Current release -The current preview release for the Oracle WebCenter Portal domain deployment on Kubernetes is [21.2.1](https://github.com/oracle/fmw-kubernetes/releases). This release uses the WebLogic Kubernetes Operator version [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/releases). +The current preview release for the Oracle WebCenter Portal domain deployment on Kubernetes is [21.2.2](https://github.com/oracle/fmw-kubernetes/releases). This release uses the WebLogic Kubernetes Operator version [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/releases). #### Recent changes and known issues From 03d8f83b442a96506fa8e68e55d33060d07ab7c5 Mon Sep 17 00:00:00 2001 From: Anand Sirasagi Date: Tue, 6 Jul 2021 10:57:37 +0530 Subject: [PATCH 5/8] Oracle WebCenter Portal 12.2.1.4.0 on Kubernetes Signed-off-by: Anand Sirasagi --- .../common/createWebCenterPortalDomain.py | 2 +- .../content/wcportal-domains/_index.md | 2 +- .../appendix/additional-configuration.md | 46 +++++++++++++++++++ .../create-or-update-image/_index.md | 2 +- .../prepare-your-environment/_index.md | 2 +- .../configure-load-balancer/nginx.md | 2 +- .../configure-load-balancer/traefik.md | 6 +-- .../content/wcportal-domains/release-notes.md | 3 +- 8 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 docs-source/content/wcportal-domains/appendix/additional-configuration.md diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py index d34fb8ea5..95db06a61 100755 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py @@ -35,7 +35,7 @@ class WCPortal12214Provisioner: '@@ORACLE_HOME@@/wcportal/common/templates/wls/oracle.wc_spaces_template.jar', '@@ORACLE_HOME@@/wcportal/common/templates/wls/oracle.analyticscollector_template.jar' ], - 'serverGroupsToTarget' : [ 'SPACES-MGD-SVRS' ] + 'serverGroupsToTarget' : [ 'SPACES-MGD-SVRS', 'AS-MGD-SVRS' ] } def __init__(self, oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName): diff --git a/docs-source/content/wcportal-domains/_index.md b/docs-source/content/wcportal-domains/_index.md index c55eca167..77372658f 100644 --- a/docs-source/content/wcportal-domains/_index.md +++ b/docs-source/content/wcportal-domains/_index.md @@ -21,7 +21,7 @@ The operator has several key features to assist you with deploying and managing * Monitor the Oracle WebCenter Portal instance using Prometheus and Grafana. #### Current release -The current preview release for the Oracle WebCenter Portal domain deployment on Kubernetes is [21.2.2](https://github.com/oracle/fmw-kubernetes/releases). This release uses the WebLogic Kubernetes Operator version [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/releases). +The current production release for the Oracle WebCenter Portal domain deployment on Kubernetes is [21.2.3](https://github.com/oracle/fmw-kubernetes/releases). This release uses the WebLogic Kubernetes Operator version [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/releases). #### Recent changes and known issues diff --git a/docs-source/content/wcportal-domains/appendix/additional-configuration.md b/docs-source/content/wcportal-domains/appendix/additional-configuration.md new file mode 100644 index 000000000..5771d4817 --- /dev/null +++ b/docs-source/content/wcportal-domains/appendix/additional-configuration.md @@ -0,0 +1,46 @@ +--- +title: "Additional Configuration" +weight: 4 +pre : " " +description: "Describes how to create connections to Oracle WebCenter Content Server to enable content integration within Oracle WebCenter Portal." +--- + +### Creating a Connection to Oracle WebCenter Content Server + +To enable content integration within Oracle WebCenter Portal create a connection to Oracle WebCenter Content Server using JAX-WS. Follow the steps in the documentation [link](https://docs.oracle.com/en/middleware/webcenter/portal/12.2.1.4/admin/managing-connections-oracle-webcenter-content-server.html#GUID-7907C8EA-802F-40B6-A19B-B0CC55CDB532) to create the connection. + +>Note: If the Oracle WebCenter Content Server is configured with SSL, before creating the connection, the SSL certificate should be imported into any location under mount path of domain persistent volume to avoid loss of certificate due pod restart. + +### Import SSL Certificate +Import the certificate using below sample command, update the keystore location to a directory under mount path of the domain persistent volume : +``` +kubectl exec -it wcp-domain-adminserver -n wcpns /bin/bash +cd $JAVA_HOME/bin +./keytool -importcert -alias collab_cert -file /filepath/sslcertificate/contentcert.crt -keystore /u01/oracle/user_projects/domains/wcp-domain/DemoTrust.jks + +``` + +### Update the TrustStore +To update the truststore location edit `domain.yaml` file, append `-Djavax.net.ssl.trustStore` to the `spec.serverPod.env.JAVA_OPTIONS` environment variable value. The truststore location used in `-Djavax.net.ssl.trustStore` option should be same as keystore location where the SSL certificate has been imported. +```yaml +serverPod: + # an (optional) list of environment variable to be set on the servers + env: + - name: JAVA_OPTIONS + value: "-Dweblogic.StdoutDebugEnabled=true -Dweblogic.ssl.Enabled=true -Dweblogic.security.SSL.ignoreHostnameVerification=true -Djavax.net.ssl.trustStore=/u01/oracle/user_projects/domains/wcp-domain/DemoTrust.jks" + - name: USER_MEM_ARGS + value: "-Djava.security.egd=file:/dev/./urandom -Xms256m -Xmx1024m " + volumes: + - name: weblogic-domain-storage-volume + persistentVolumeClaim: + claimName: wcp-domain-domains-pvc + volumeMounts: + - mountPath: /u01/oracle/user_projects/domains + name: weblogic-domain-storage-volume +``` + +Apply the `domain.yaml` file to restart the Oracle WebCenter Portal domain. + +```bash +kubectl apply -f domain.yaml +``` \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/create-or-update-image/_index.md b/docs-source/content/wcportal-domains/create-or-update-image/_index.md index 5515d5115..287554423 100644 --- a/docs-source/content/wcportal-domains/create-or-update-image/_index.md +++ b/docs-source/content/wcportal-domains/create-or-update-image/_index.md @@ -117,7 +117,7 @@ After [setting up the WebLogic Image Tool]({{< relref "/wcportal-domains/create- You must download the required Oracle WebCenter Portal installation binaries and patches listed below from the [Oracle Software Delivery Cloud](https://edelivery.oracle.com/) and save them in a directory of your choice. In these steps, the directory is `download location`. -The installation binaries and patches required for release 21.2.1 are: +The installation binaries and patches required for release 21.2.3 are: * JDK: * jdk-8u281-linux-x64.tar.gz diff --git a/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md b/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md index cf88a9785..9577ed9aa 100644 --- a/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md +++ b/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md @@ -99,7 +99,7 @@ Oracle WebCenter Portal domain deployment on Kubernetes leverages the WebLogic K 1. Download the WebCenter Portal Kubernetes deployment scripts from this [repository](https://github.com/oracle/fmw-kubernetes.git) and copy them in to WebLogic operator samples location. ```bash - $ git clone https://github.com/oracle/fmw-kubernetes.git --branch release/21.2.2 + $ git clone https://github.com/oracle/fmw-kubernetes.git --branch release/21.2.3 $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/create-wcp-domain ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/ingress-per-domain ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md index c7e3c10e6..f1156e310 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md @@ -7,7 +7,7 @@ pre = "b. " description = "Configure the ingress-based NGINX load balancer for an Oracle WebCenter Portal domain." +++ -To load balance Oracle WebCenter Portal domain clusters, you can install the ingress-based *NGINX* load balancer and configure NGINX for both SSL and non-SSL access of the application URL. +To load balance Oracle WebCenter Portal domain clusters, you can install the ingress-based *NGINX* load balancer and configure NGINX for non-SSL, SSL termination, and end-to-end SSL access of the application URL. Follow these steps to set up NGINX as a load balancer for an Oracle WebCenter Portal domain in a Kubernetes cluster: See the official [installation document](https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx#prerequisites) for prerequisites. diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md index e3e2857a9..09158b534 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md @@ -7,7 +7,7 @@ pre = "a. " description = "Configure the ingress-based Traefik load balancer for an Oracle WebCenter Portal domain." +++ -To load balance Oracle WebCenter Portal domain clusters, you can install the ingress-based *Traefik* load balancer (version 2.2.1 or later for production deployments) and configure it for non-SSL and SSL-based access of the application URL.Follow these steps to set up Traefik as a load balancer for an Oracle WebCenter Portal domain in a Kubernetes cluster: +To load balance Oracle WebCenter Portal domain clusters, you can install the ingress-based *Traefik* load balancer (version 2.2.1 or later for production deployments) and configure it for non-SSL, SSL termination, and end-to-end SSL access of the application URL. Follow these steps to set up Traefik as a load balancer for an Oracle WebCenter Portal domain in a Kubernetes cluster: * [ Non-SSL and SSL termination](#non-ssl-and-ssl-termination) 1. [Install the Traefik (ingress-based) load balancer](#install-the-traefik-ingress-based-load-balancer) @@ -409,7 +409,7 @@ $ helm delete wcp-traefik-ingress -n wcpns pod/traefik-845f5d6dbb-swb96 1/1 Running 0 32s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - service/traefik LoadBalancer 10.99.52.249 9000:31288/TCP,30305:30305/TCP,30443:30443/TCP 32s + service/traefik NodePort 10.99.52.249 9000:31288/TCP,30305:30305/TCP,30443:30443/TCP 32s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/traefik 1/1 1 1 33s @@ -446,7 +446,7 @@ $ helm upgrade traefik traefik/traefik --namespace traefik --reuse-values \ {{% /expand %}} #### Create IngressRouteTCP - +1. For each backend service, create different ingresses, as Traefik does not support multiple paths or rules with annotation `ssl-passthrough`. For example, for `wcp-domain-adminserver` and `wcp-domain-cluster-wcp-cluster,` different ingresses must be created. 1. To enable SSL passthrough in Traefik, you can configure a TCP router. A sample YAML for `IngressRouteTCP` is available at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls/traefik-tls.yaml`. The following should be updated in `traefik-tls.yaml`: * The service name and the SSL port should be updated in the `services`. * The load balancer host name should be updated in the `HostSNI` rule. diff --git a/docs-source/content/wcportal-domains/release-notes.md b/docs-source/content/wcportal-domains/release-notes.md index 7bd9eecb6..1d076c0af 100644 --- a/docs-source/content/wcportal-domains/release-notes.md +++ b/docs-source/content/wcportal-domains/release-notes.md @@ -9,6 +9,5 @@ pre: "1. " | Date | Version | Change | --- | --- | --- | -| May 27, 2021 | 21.2.2 | Only Oracle Portal 12.2.1.4 is supported and certified with the WebLogic Kubernetes operator version 3.1.1. +| June 30, 2021 | 21.2.3 | Only Oracle Portal 12.2.1.4 is supported and certified with the WebLogic Kubernetes operator version 3.1.1. ->Note: This is a preview release. \ No newline at end of file From 8c0b0daabd0d51feecaeb570f7dd84408c92edcf Mon Sep 17 00:00:00 2001 From: Anand Sirasagi Date: Tue, 6 Jul 2021 17:28:02 +0530 Subject: [PATCH 6/8] Oracle WebCenter Portal 12.2.1.4.0 on Kubernetes Signed-off-by: Anand Sirasagi --- .../wcportal-domains/appendix/additional-configuration.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs-source/content/wcportal-domains/appendix/additional-configuration.md b/docs-source/content/wcportal-domains/appendix/additional-configuration.md index 5771d4817..d5bd51c91 100644 --- a/docs-source/content/wcportal-domains/appendix/additional-configuration.md +++ b/docs-source/content/wcportal-domains/appendix/additional-configuration.md @@ -14,9 +14,9 @@ To enable content integration within Oracle WebCenter Portal create a connection ### Import SSL Certificate Import the certificate using below sample command, update the keystore location to a directory under mount path of the domain persistent volume : ``` -kubectl exec -it wcp-domain-adminserver -n wcpns /bin/bash -cd $JAVA_HOME/bin -./keytool -importcert -alias collab_cert -file /filepath/sslcertificate/contentcert.crt -keystore /u01/oracle/user_projects/domains/wcp-domain/DemoTrust.jks +$ kubectl exec -it wcp-domain-adminserver -n wcpns /bin/bash +$ cd $JAVA_HOME/bin +$ ./keytool -importcert -alias collab_cert -file /filepath/sslcertificate/contentcert.crt -keystore /u01/oracle/user_projects/domains/wcp-domain/DemoTrust.jks ``` From c99cc37c856f4f1ecc9ff568be3f906d63f38b2c Mon Sep 17 00:00:00 2001 From: Anand Sirasagi Date: Tue, 6 Jul 2021 17:29:47 +0530 Subject: [PATCH 7/8] Oracle WebCenter Portal 12.2.1.4.0 on Kubernetes Signed-off-by: Anand Sirasagi --- .../wcportal-domains/appendix/additional-configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-source/content/wcportal-domains/appendix/additional-configuration.md b/docs-source/content/wcportal-domains/appendix/additional-configuration.md index d5bd51c91..878e2a9fe 100644 --- a/docs-source/content/wcportal-domains/appendix/additional-configuration.md +++ b/docs-source/content/wcportal-domains/appendix/additional-configuration.md @@ -42,5 +42,5 @@ serverPod: Apply the `domain.yaml` file to restart the Oracle WebCenter Portal domain. ```bash -kubectl apply -f domain.yaml +$ kubectl apply -f domain.yaml ``` \ No newline at end of file From b505c9c95e94431c24582558514b8b3b37138e22 Mon Sep 17 00:00:00 2001 From: Anand Sirasagi Date: Tue, 7 Jun 2022 16:43:24 +0530 Subject: [PATCH 8/8] WCP-32533 :- Publishing Oracle WebCenter Portal scripts for operator 3.3.0 Signed-off-by: Anand Sirasagi --- OracleWebCenterPortal/kubernetes/README.md | 15 - .../charts/apache-samples/README.md | 8 + .../apache-samples/custom-sample/README.md | 149 + .../apache-samples/custom-sample/certgen.sh | 51 + .../custom-sample/custom_mod_wl_apache.conf | 37 + .../apache-samples/custom-sample/input.yaml | 28 + .../apache-samples/default-sample/README.md | 39 + .../charts/apache-webtier/Chart.yaml | 20 + .../charts/apache-webtier/README.md | 92 + .../apache-webtier/templates/_helpers.tpl | 25 + .../templates/cluster-role-binding.yaml | 17 + .../templates/cluster-role.yaml | 29 + .../apache-webtier/templates/deployment.yaml | 106 + .../apache-webtier/templates/secret.yaml | 14 + .../templates/service-account.yaml | 8 + .../apache-webtier/templates/service.yaml | 28 + .../charts/apache-webtier/values.yaml | 79 + .../ingress-per-domain/Chart.yaml | 4 +- .../templates/nginx-ingress-k8s1.19.yaml | 101 + .../templates/nginx-ingress.yaml | 77 + .../templates/traefik-ingress-k8s1.19.yaml | 110 + .../templates/traefik-ingress.yaml | 87 + .../ingress-per-domain/tls/nginx-tls.yaml | 4 +- .../ingress-per-domain/tls/traefik-tls.yaml | 2 +- .../charts/ingress-per-domain/values.yaml | 43 + .../kubernetes/charts/traefik/values.yaml | 84 +- .../charts/weblogic-operator/.helmignore | 12 + .../charts/weblogic-operator/Chart.yaml | 10 + .../templates/_domain-namespaces.tpl | 134 + .../_operator-clusterrole-domain-admin.tpl | 40 + .../_operator-clusterrole-general.tpl | 39 + .../_operator-clusterrole-namespace.tpl | 40 + .../_operator-clusterrole-nonresource.tpl | 15 + .../_operator-clusterrole-operator-admin.tpl | 34 + ...ator-clusterrolebinding-auth-delegator.tpl | 30 + ..._operator-clusterrolebinding-discovery.tpl | 30 + .../_operator-clusterrolebinding-general.tpl | 35 + ...perator-clusterrolebinding-nonresource.tpl | 21 + .../templates/_operator-cm.tpl | 58 + .../templates/_operator-dep.tpl | 158 + .../templates/_operator-external-svc.tpl | 30 + .../templates/_operator-internal-svc.tpl | 20 + .../templates/_operator-role.tpl | 17 + .../_operator-rolebinding-namespace.tpl | 35 + .../templates/_operator-rolebinding.tpl | 22 + .../templates/_operator-secret.tpl | 25 + .../weblogic-operator/templates/_operator.tpl | 30 + .../weblogic-operator/templates/_utils.tpl | 493 +++ .../templates/_validate-inputs.tpl | 63 + .../weblogic-operator/templates/main.yaml | 11 + .../charts/weblogic-operator/values.yaml | 224 ++ .../kubernetes/common/createFMWJRFDomain.py | 332 ++ .../common/createFMWRestrictedJRFDomain.py | 291 ++ .../kubernetes/common/domain-template.yaml | 119 + .../common/jrf-domain-template.yaml | 123 + .../kubernetes/common/utility.sh | 928 +++++ .../kubernetes/common/validate.sh | 481 +++ .../kubernetes/common/wdt-and-wit-utility.sh | 439 +++ ...create-azure-storage-credentials-secret.sh | 92 + .../create-docker-credentials-secret.sh | 106 + .../create-oracle-db-service/README.md | 76 + .../common/checkDbState.sh | 21 + .../common/oracle.db.yaml | 78 + .../create-image-pull-secret.sh | 60 + .../start-db-service.sh | 113 + .../stop-db-service.sh | 45 + .../create-rcu-credentials/README.md | 56 + .../create-rcu-credentials.sh | 139 + .../kubernetes/create-rcu-schema/README.md | 219 ++ .../common/createRepository.sh | 72 + .../common/dropRepository.sh | 66 + .../create-rcu-schema/common/rcu.yaml | 20 + .../common/template/rcu.yaml.template | 22 + .../create-image-pull-secret.sh | 59 + .../create-rcu-schema/create-rcu-schema.sh | 204 + .../create-rcu-schema/drop-rcu-schema.sh | 108 + .../common/createWebCenterPortalDomain.py | 93 +- .../create-domain-inputs.yaml | 22 +- .../create-domain-job-template.yaml | 12 +- .../domain-home-on-pv/create-domain.sh | 16 +- .../wlst/create-domain-script.sh | 7 +- .../create-wcp-domain/utils/utility.sh | 390 ++ .../utils/wcp-domain-template.yaml | 123 + .../config/config_ms.yml | 63 - .../weblogic-monitoring-exporter/get1.1.0.sh | 38 - .../README.md | 50 + .../create-weblogic-credentials.sh | 121 + .../create-weblogic-domain-pv-pvc/README.md | 222 ++ .../create-pv-pvc-inputs.yaml | 44 + .../create-pv-pvc.sh | 267 ++ .../pv-template.yaml | 21 + .../pvc-template.yaml | 17 + .../kubernetes/delete-domain/README.md | 27 + .../delete-weblogic-domain-resources.sh | 283 ++ .../kubernetes/domain-lifecycle/README.md | 186 + .../domain-lifecycle/clusterStatus.sh | 130 + .../kubernetes/domain-lifecycle/helper.sh | 1049 ++++++ .../domain-lifecycle/introspectDomain.sh | 105 + .../domain-lifecycle/restartServer.sh | 106 + .../domain-lifecycle/rollCluster.sh | 123 + .../kubernetes/domain-lifecycle/rollDomain.sh | 105 + .../domain-lifecycle/scaleCluster.sh | 122 + .../domain-lifecycle/startCluster.sh | 129 + .../domain-lifecycle/startDomain.sh | 97 + .../domain-lifecycle/startServer.sh | 242 ++ .../domain-lifecycle/stopCluster.sh | 119 + .../kubernetes/domain-lifecycle/stopDomain.sh | 95 + .../kubernetes/domain-lifecycle/stopServer.sh | 248 ++ .../elasticsearch-and-kibana/README.md | 31 + .../elasticsearch_and_kibana.yaml | 117 + .../kubernetes/imagetool-scripts/buildArgs | 1 + .../kubernetes/ingress-per-domain/README.md | 100 - .../templates/nginx-ingress.yaml | 63 - .../templates/traefik-ingress.yaml | 54 - .../templates/voyager-ingress.yaml | 79 - .../ingress-per-domain/tls/voyager-tls.yaml | 27 - .../kubernetes/ingress-per-domain/values.yaml | 41 - .../logging-services/logstash/README.md | 59 + .../logging-services/logstash/logstash.conf | 25 + .../logging-services/logstash/logstash.yaml | 39 + .../weblogic-logging-exporter/README.md | 131 + .../WebLogicLoggingExporter.yaml | 12 +- .../kubernetes/monitoring-service/README.md | 276 ++ .../config/config.yml.template} | 17 +- .../weblogic-server-dashboard-import.json | 3312 ++++++++++++++++ .../config/weblogic-server-dashboard.json | 3315 +++++++++++++++++ .../config/weblogic.xml | 0 .../monitoring-service/delete-monitoring.sh | 122 + ...ometheus-roleBinding-domain-namespace.yaml | 20 + ...metheus-roleSpecific-domain-namespace.yaml | 23 + .../wls-exporter-ServiceMonitor.yaml} | 7 +- .../wls-exporter-ServiceMonitor.yaml.template | 44 + .../monitoring-service/monitoring-inputs.yaml | 64 + .../deploy-weblogic-monitoring-exporter.py | 105 + .../deploy-weblogic-monitoring-exporter.sh | 37 + .../scripts/get-wls-exporter.sh | 46 + .../undeploy-weblogic-monitoring-exporter.py | 103 + .../undeploy-weblogic-monitoring-exporter.sh | 39 + .../monitoring-service/scripts/utils.sh | 61 + .../monitoring-service/setup-monitoring.sh | 194 + .../kubernetes/rest/README.md | 38 + .../rest/generate-external-rest-identity.sh | 200 + .../kubernetes/scaling/scalingAction.sh | 504 +++ .../content/wcportal-domains/_index.md | 13 +- .../appendix/quickstart-deployment-on-prem.md | 128 +- .../wcportal-domains/cleanup-domain-setup.md | 2 +- .../create-or-update-image/_index.md | 23 +- .../configure-wcp-search/_index.md | 10 +- .../installguide/create-wcp-domain/_index.md | 85 +- .../prepare-your-environment/_index.md | 126 +- .../installguide/prerequisites/_index.md | 12 +- .../configure-load-balancer/_index.md | 2 +- .../configure-load-balancer/apachewebtier.md | 22 +- .../configure-load-balancer/nginx.md | 70 +- .../configure-load-balancer/traefik.md | 72 +- .../configure-load-balancer/voyager.md | 526 --- .../monitoring-domain/_index.md | 310 +- .../publishing-logs/_index.md | 2 +- .../publishing-logs/fluentd/_index.md | 26 +- .../publishing-logs/weblogiclogging/_index.md | 9 +- .../content/wcportal-domains/release-notes.md | 3 +- 161 files changed, 20978 insertions(+), 1593 deletions(-) delete mode 100755 OracleWebCenterPortal/kubernetes/README.md create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-samples/README.md create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/README.md create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/certgen.sh create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/custom_mod_wl_apache.conf create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/input.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-samples/default-sample/README.md create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/Chart.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/README.md create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/_helpers.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/cluster-role-binding.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/cluster-role.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/deployment.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/secret.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/service-account.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/service.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/apache-webtier/values.yaml rename OracleWebCenterPortal/kubernetes/{ => charts}/ingress-per-domain/Chart.yaml (80%) mode change 100755 => 100644 create mode 100644 OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/nginx-ingress-k8s1.19.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/nginx-ingress.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/traefik-ingress-k8s1.19.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/traefik-ingress.yaml rename OracleWebCenterPortal/kubernetes/{ => charts}/ingress-per-domain/tls/nginx-tls.yaml (89%) mode change 100755 => 100644 rename OracleWebCenterPortal/kubernetes/{ => charts}/ingress-per-domain/tls/traefik-tls.yaml (96%) mode change 100755 => 100644 create mode 100644 OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/values.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/.helmignore create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/Chart.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_domain-namespaces.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-domain-admin.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-general.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-namespace.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-nonresource.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-operator-admin.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-auth-delegator.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-discovery.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-general.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-nonresource.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-cm.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-dep.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-external-svc.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-internal-svc.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-role.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-rolebinding-namespace.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-rolebinding.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-secret.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_utils.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_validate-inputs.tpl create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/main.yaml create mode 100644 OracleWebCenterPortal/kubernetes/charts/weblogic-operator/values.yaml create mode 100644 OracleWebCenterPortal/kubernetes/common/createFMWJRFDomain.py create mode 100644 OracleWebCenterPortal/kubernetes/common/createFMWRestrictedJRFDomain.py create mode 100644 OracleWebCenterPortal/kubernetes/common/domain-template.yaml create mode 100644 OracleWebCenterPortal/kubernetes/common/jrf-domain-template.yaml create mode 100644 OracleWebCenterPortal/kubernetes/common/utility.sh create mode 100644 OracleWebCenterPortal/kubernetes/common/validate.sh create mode 100644 OracleWebCenterPortal/kubernetes/common/wdt-and-wit-utility.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-kubernetes-secrets/create-azure-storage-credentials-secret.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-kubernetes-secrets/create-docker-credentials-secret.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-oracle-db-service/README.md create mode 100644 OracleWebCenterPortal/kubernetes/create-oracle-db-service/common/checkDbState.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-oracle-db-service/common/oracle.db.yaml create mode 100644 OracleWebCenterPortal/kubernetes/create-oracle-db-service/create-image-pull-secret.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-oracle-db-service/start-db-service.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-oracle-db-service/stop-db-service.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-credentials/README.md create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-credentials/create-rcu-credentials.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-schema/README.md create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-schema/common/createRepository.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-schema/common/dropRepository.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-schema/common/rcu.yaml create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-schema/common/template/rcu.yaml.template create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-schema/create-image-pull-secret.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-schema/create-rcu-schema.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-rcu-schema/drop-rcu-schema.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/utility.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/wcp-domain-template.yaml delete mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_ms.yml delete mode 100755 OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/get1.1.0.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-weblogic-domain-credentials/README.md create mode 100644 OracleWebCenterPortal/kubernetes/create-weblogic-domain-credentials/create-weblogic-credentials.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/README.md create mode 100644 OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/create-pv-pvc-inputs.yaml create mode 100644 OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/create-pv-pvc.sh create mode 100644 OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/pv-template.yaml create mode 100644 OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/pvc-template.yaml create mode 100644 OracleWebCenterPortal/kubernetes/delete-domain/README.md create mode 100644 OracleWebCenterPortal/kubernetes/delete-domain/delete-weblogic-domain-resources.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/README.md create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/clusterStatus.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/helper.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/introspectDomain.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/restartServer.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/rollCluster.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/rollDomain.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/scaleCluster.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/startCluster.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/startDomain.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/startServer.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/stopCluster.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/stopDomain.sh create mode 100644 OracleWebCenterPortal/kubernetes/domain-lifecycle/stopServer.sh create mode 100644 OracleWebCenterPortal/kubernetes/elasticsearch-and-kibana/README.md create mode 100644 OracleWebCenterPortal/kubernetes/elasticsearch-and-kibana/elasticsearch_and_kibana.yaml delete mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/README.md delete mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/nginx-ingress.yaml delete mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/traefik-ingress.yaml delete mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/voyager-ingress.yaml delete mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/voyager-tls.yaml delete mode 100755 OracleWebCenterPortal/kubernetes/ingress-per-domain/values.yaml create mode 100644 OracleWebCenterPortal/kubernetes/logging-services/logstash/README.md create mode 100644 OracleWebCenterPortal/kubernetes/logging-services/logstash/logstash.conf create mode 100644 OracleWebCenterPortal/kubernetes/logging-services/logstash/logstash.yaml create mode 100644 OracleWebCenterPortal/kubernetes/logging-services/weblogic-logging-exporter/README.md rename OracleWebCenterPortal/kubernetes/{create-wcp-domain/utils => logging-services}/weblogic-logging-exporter/WebLogicLoggingExporter.yaml (61%) mode change 100755 => 100644 create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/README.md rename OracleWebCenterPortal/kubernetes/{create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_as.yml => monitoring-service/config/config.yml.template} (98%) mode change 100755 => 100644 create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic-server-dashboard-import.json create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic-server-dashboard.json rename OracleWebCenterPortal/kubernetes/{create-wcp-domain/utils/weblogic-monitoring-exporter => monitoring-service}/config/weblogic.xml (100%) mode change 100755 => 100644 create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/delete-monitoring.sh create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/manifests/prometheus-roleBinding-domain-namespace.yaml create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/manifests/prometheus-roleSpecific-domain-namespace.yaml rename OracleWebCenterPortal/kubernetes/{create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml => monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml} (90%) mode change 100755 => 100644 create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml.template create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/monitoring-inputs.yaml create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/scripts/deploy-weblogic-monitoring-exporter.py create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/scripts/deploy-weblogic-monitoring-exporter.sh create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/scripts/get-wls-exporter.sh create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/scripts/undeploy-weblogic-monitoring-exporter.py create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/scripts/undeploy-weblogic-monitoring-exporter.sh create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/scripts/utils.sh create mode 100644 OracleWebCenterPortal/kubernetes/monitoring-service/setup-monitoring.sh create mode 100644 OracleWebCenterPortal/kubernetes/rest/README.md create mode 100644 OracleWebCenterPortal/kubernetes/rest/generate-external-rest-identity.sh create mode 100644 OracleWebCenterPortal/kubernetes/scaling/scalingAction.sh delete mode 100644 docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/voyager.md diff --git a/OracleWebCenterPortal/kubernetes/README.md b/OracleWebCenterPortal/kubernetes/README.md deleted file mode 100755 index 80153b2a0..000000000 --- a/OracleWebCenterPortal/kubernetes/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Oracle WebCenter Portal on Kubernetes - -This directory provides the open source samples which have several key features to assist you with deploying and managing WebCenter Portal in a Kubernetes environment. You can do the following: - -* Create WebCenter Portal instances in a Kubernetes persistent volume. This persistent volume can reside in an NFS file system or other Kubernetes volume types. -* Start servers based on declarative startup parameters and desired states. -* Expose the WebCenter Portal Services for external access. -* Configure WebCenter Portal for Search. -* Publish WebLogic Kubernetes Operator and WebLogic Server logs into Elasticsearch and interact with them in Kibana. -* Monitor the instance using Prometheus and Grafana - -#### Getting started - -Refer the following documentation link for detailed information about deploying Oracle WebCenter Portal domain on Kubernetes. -[Documentation](https://oracle.github.io/fmw-kubernetes/wcportal-domains/) diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-samples/README.md b/OracleWebCenterPortal/kubernetes/charts/apache-samples/README.md new file mode 100644 index 000000000..dcaab57c7 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-samples/README.md @@ -0,0 +1,8 @@ +# Apache load balancer samples + +The sample package contains two samples that use the [Apache Helm chart](../apache-webtier/README.md). The samples use the Docker image for the Apache HTTP Server with the 12.2.1.3.0 and 12.2.1.4.0 Oracle WebLogic Server Proxy Plugin. See the details in [Apache HTTP Server with Oracle WebLogic Server Proxy Plugin on Docker](https://github.com/oracle/docker-images/tree/master/OracleWebLogic/samples/12213-webtier-apache). + +* [The default sample](default-sample/README.md) uses the built-in configuration in the Docker image. + +* [The custom sample](custom-sample/README.md) demonstrates how to customize the configuration of the Apache HTTP Server with the 12.2.1.3.0 and 12.2.1.4.0 Oracle WebLogic Server Proxy Plugins. + diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/README.md b/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/README.md new file mode 100644 index 000000000..c35d2d700 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/README.md @@ -0,0 +1,149 @@ +# Apache load balancer custom sample +In this sample, we will configure the Apache webtier as a load balancer for multiple WebLogic domains using a custom configuration. We will demonstrate how to use the Apache webtier to handle traffic to multiple backend WebLogic domains. + +## 1. Create a namespace +In this sample, both the Apache webtier and WebLogic domain instances are located in the namespace `apache-sample`. +```shell +$ kubectl create namespace apache-sample +``` + +## 2. Create WebLogic domains +We need to prepare some backend domains for load balancing by the Apache webtier. Refer to the [sample](/kubernetes/samples/scripts/create-weblogic-domain/domain-home-on-pv/README.md), to create two WebLogic domains under the namespace `apache-sample`. + +The first domain uses the following custom configuration parameters: +- namespace: `apache-sample` +- domainUID: `domain1` +- clusterName: `cluster-1` +- adminServerName: `admin-server` +- adminPort: `7001` +- adminNodePort: `30701` +- managedServerPort: `8001` + +The second domain uses the following custom configuration parameters: +- namespace: `apache-sample` +- domainUID: `domain2` +- clusterName: `cluster-1` +- adminServerName: `admin-server` +- adminPort: `7011` +- adminNodePort: `30702` +- managedServerPort: `8021` + +After the domains are successfully created, deploy the sample web application, `testwebapp.war`, on each domain cluster using the WLS Administration Console. The sample web application is located in the `kubernetes/samples/charts/application` directory. + +## 3. Build the Apache webtier Docker image +Refer to the [sample](https://github.com/oracle/docker-images/tree/master/OracleWebLogic/samples/12213-webtier-apache), to build the Apache webtier Docker image. + +## 4. Provide the custom Apache plugin configuration +In this sample, we will provide a custom Apache plugin configuration to fine tune the behavior of Apache. + +* Create a custom Apache plugin configuration file named `custom_mod_wl_apache.conf`. The file content is similar to below. + +``` +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + + +WebLogicHost ${WEBLOGIC_HOST} +WebLogicPort ${WEBLOGIC_PORT} + + +# Directive for weblogic admin Console deployed on Weblogic Admin Server + +SetHandler weblogic-handler +WebLogicHost domain1-admin-server +WebLogicPort ${WEBLOGIC_PORT} + + +# Directive for all application deployed on weblogic cluster with a prepath defined by LOCATION variable +# For example, if the LOCAITON is set to '/weblogic', all applications deployed on the cluster can be accessed via +# http://myhost:myport/weblogic/application_end_url +# where 'myhost' is the IP of the machine that runs the Apache web tier, and +# 'myport' is the port that the Apache web tier is publicly exposed to. +# Note that LOCATION cannot be set to '/' unless this is the only Location module configured. + +WLSRequest On +WebLogicCluster domain1-cluster-cluster-1:8001 +PathTrim /weblogic1 + + +# Directive for all application deployed on weblogic cluster with a prepath defined by LOCATION2 variable +# For example, if the LOCAITON2 is set to '/weblogic2', all applications deployed on the cluster can be accessed via +# http://myhost:myport/weblogic2/application_end_url +# where 'myhost' is the IP of the machine that runs the Apache web tier, and +# 'myport' is the port that the Apache webt ier is publicly exposed to. + +WLSRequest On +WebLogicCluster domain2-cluster-cluster-1:8021 +PathTrim /weblogic2 + +``` + +* Create a PV / PVC (pv-claim-name) that can be used to store the `custom_mod_wl_apache.conf`. Refer to the [Sample for creating a PV or PVC](/kubernetes/samples/scripts/create-weblogic-domain-pv-pvc/README.md). + +## 5. Prepare your own certificate and private key +In production, Oracle strongly recommends that you provide your own certificates. Run the following commands to generate your own certificate and private key using `openssl`. + +```shell +$ cd kubernetes/samples/charts/apache-samples/custom-sample +$ export VIRTUAL_HOST_NAME=apache-sample-host +$ export SSL_CERT_FILE=apache-sample.crt +$ export SSL_CERT_KEY_FILE=apache-sample.key +$ sh certgen.sh +``` + +## 6. Prepare the input values for the Apache webtier Helm chart +Run the following commands to prepare the input value file for the Apache webtier Helm chart. + +```shell +$ base64 -i ${SSL_CERT_FILE} | tr -d '\n' +$ base64 -i ${SSL_CERT_KEY_FILE} | tr -d '\n' +$ touch input.yaml +``` +Edit the input parameters file, `input.yaml`. The file content is similar to below. + +```yaml +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# Use this to provide your own Apache webtier configuration as needed; simply define this +# Persistence Volume which contains your own custom_mod_wl_apache.conf file. +persistentVolumeClaimName: + +# The VirtualHostName of the Apache HTTP server. It is used to enable custom SSL configuration. +virtualHostName: apache-sample-host + +# The customer supplied certificate to use for Apache webtier SSL configuration. +# The value must be a string containing a base64 encoded certificate. Run following command to get it. +# base64 -i ${SSL_CERT_FILE} | tr -d '\n' +customCert: + +# The customer supplied private key to use for Apache webtier SSL configuration. +# The value must be a string containing a base64 encoded key. Run following command to get it. +# base64 -i ${SSL_KEY_FILE} | tr -d '\n' +customKey: +``` + +## 7. Install the Apache webtier Helm chart +The Apache webtier Helm chart is located in the `kubernetes/samples/charts/apache-webtier` directory. Install the Apache webtier Helm chart to the `apache-sample` namespace with the specified input parameters: + +```shell +$ cd kubernetes/samples/charts +$ helm install my-release --values apache-samples/custom-sample/input.yaml --namespace apache-sample apache-webtier +``` + +## 8. Run the sample application +Now you can send requests to different WebLogic domains with the unique entry point of Apache with different paths. Alternatively, you can access the URLs in a web browser. +```shell +$ curl --silent http://${HOSTNAME}:30305/weblogic1/testwebapp/ +$ curl --silent http://${HOSTNAME}:30305/weblogic2/testwebapp/ +``` +Also, you can use SSL URLs to send requests to different WebLogic domains. Access the SSL URL via the `curl` command or a web browser. +```shell +$ curl -k --silent https://${HOSTNAME}:30443/weblogic1/testwebapp/ +$ curl -k --silent https://${HOSTNAME}:30443/weblogic2/testwebapp/ +``` + +## 9. Uninstall the Apache webtier +```shell +$ helm uninstall my-release --namespace apache-sample +``` diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/certgen.sh b/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/certgen.sh new file mode 100644 index 000000000..20dd9fa51 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/certgen.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Since: June, 2018 +# Author: dongbo.xiao@oracle.com +# Description: script to start Apache HTTP Server +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + +# Generated configuration file +CONFIG_FILE="config.txt" + +cat > $CONFIG_FILE <<-EOF +[req] +default_bits = 2048 +prompt = no +default_md = sha256 +req_extensions=v3_req +extensions=v3_req +distinguished_name = dn + +[dn] +C = US +ST = CA +L = Redwood Shores +O = Oracle Corporation +OU = Apache HTTP Server With Plugin +CN = $VIRTUAL_HOST_NAME + +[v3_req] +subjectAltName = @alt_names +[alt_names] +DNS.1 = $VIRTUAL_HOST_NAME +DNS.2 = $VIRTUAL_HOST_NAME.cloud.oracle.com +DNS.3 = *.$VIRTUAL_HOST_NAME +DNS.4 = localhost +EOF + +echo "Generating certs for $VIRTUAL_HOST_NAME" + +# Generate our Private Key, CSR and Certificate +# Use SHA-2 as SHA-1 is unsupported from Jan 1, 2017 + +openssl req -x509 -newkey rsa:2048 -sha256 -nodes -keyout "$SSL_CERT_KEY_FILE" -days 3650 -out "$SSL_CERT_FILE" -config "$CONFIG_FILE" + +# OPTIONAL - write an info to see the details of the generated crt +openssl x509 -noout -fingerprint -text < "$SSL_CERT_FILE" > "$SSL_CERT_FILE.info" +# Protect the key +chmod 400 "$SSL_CERT_KEY_FILE" +chmod 400 "$SSL_CERT_FILE.info" diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/custom_mod_wl_apache.conf b/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/custom_mod_wl_apache.conf new file mode 100644 index 000000000..8a2d05f0d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/custom_mod_wl_apache.conf @@ -0,0 +1,37 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + + +WebLogicHost ${WEBLOGIC_HOST} +WebLogicPort ${WEBLOGIC_PORT} + + +# Directive for weblogic admin Console deployed on Weblogic Admin Server + +SetHandler weblogic-handler +WebLogicHost domain1-admin-server +WebLogicPort ${WEBLOGIC_PORT} + + +# Directive for all application deployed on weblogic cluster with a prepath defined by LOCATION variable +# For example, if the LOCAITON is set to '/weblogic', all applications deployed on the cluster can be accessed via +# http://myhost:myport/weblogic/application_end_url +# where 'myhost' is the IP of the machine that runs the Apache web tier, and +# 'myport' is the port that the Apache web tier is publicly exposed to. +# Note that LOCATION cannot be set to '/' unless this is the only Location module configured. + +WLSRequest On +WebLogicCluster domain1-cluster-cluster-1:8001 +PathTrim /weblogic1 + + +# Directive for all application deployed on weblogic cluster with a prepath defined by LOCATION2 variable +# For example, if the LOCAITON2 is set to '/weblogic2', all applications deployed on the cluster can be accessed via +# http://myhost:myport/weblogic2/application_end_url +# where 'myhost' is the IP of the machine that runs the Apache web tier, and +# 'myport' is the port that the Apache webt ier is publicly exposed to. + +WLSRequest On +WebLogicCluster domain2-cluster-cluster-1:8021 +PathTrim /weblogic2 + diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/input.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/input.yaml new file mode 100644 index 000000000..95eaec6e9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-samples/custom-sample/input.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# Use this to provide your own Apache webtier configuration as needed; simply define the +# Persistence Volume which contains your own custom_mod_wl_apache.conf file and provide the Persistence Volume Claim Name +persistentVolumeClaimName: + +# imagePullSecrets contains an optional list of Kubernetes secrets, that are needed +# to access the registry containing the apache webtier image. +# If no secrets are required, then omit this property. +# +# Example : a secret is needed, and has been stored in 'my-apache-webtier-secret' +# +# imagePullSecrets: +# - name: my-apache-webtier-secret + +# The VirtualHostName of the Apache HTTP server. It is used to enable custom SSL configuration. +virtualHostName: apache-sample-host + +# The customer supplied certificate to use for Apache webtier SSL configuration. +# The value must be a string containing a base64 encoded certificate. Run following command to get it. +# base64 -i ${SSL_CERT_FILE} | tr -d '\n' +customCert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURxakNDQXBJQ0NRQ0w2Q2JwRWZ6QnB6QU5CZ2txaGtpRzl3MEJBUXNGQURDQmxqRUxNQWtHQTFVRUJoTUMKVlZNeEN6QUpCZ05WQkFnTUFrTkJNUmN3RlFZRFZRUUhEQTVTWldSM2IyOWtJRk5vYjNKbGN6RWJNQmtHQTFVRQpDZ3dTVDNKaFkyeGxJRU52Y25CdmNtRjBhVzl1TVNjd0pRWURWUVFMREI1QmNHRmphR1VnU0ZSVVVDQlRaWEoyClpYSWdWMmwwYUNCUWJIVm5hVzR4R3pBWkJnTlZCQU1NRW1Gd1lXTm9aUzF6WVcxd2JHVXRhRzl6ZERBZUZ3MHgKT0RFeE1UUXhOVEF3TURGYUZ3MHlPREV4TVRFeE5UQXdNREZhTUlHV01Rc3dDUVlEVlFRR0V3SlZVekVMTUFrRwpBMVVFQ0F3Q1EwRXhGekFWQmdOVkJBY01EbEpsWkhkdmIyUWdVMmh2Y21Wek1Sc3dHUVlEVlFRS0RCSlBjbUZqCmJHVWdRMjl5Y0c5eVlYUnBiMjR4SnpBbEJnTlZCQXNNSGtGd1lXTm9aU0JJVkZSUUlGTmxjblpsY2lCWGFYUm8KSUZCc2RXZHBiakViTUJrR0ExVUVBd3dTWVhCaFkyaGxMWE5oYlhCc1pTMW9iM04wTUlJQklqQU5CZ2txaGtpRwo5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeXBVWjEzV3ltcUVnSUZOVTZDa2E0SkFqMXFNemZ4T2FjTklNClVKRE9zZUtqdjNOYmpJb0szQTArcE9lRDNPOXBNcUVxM3F5ZWlCTUtnVEQwREhZNS9HQldjeEUvdUJyWk0rQzgKcnl3RVk5QTl5Y1drZ3h4NUFqSFM1ZnRLMFhpQU9OZWdnUnV0RTBTTnRmbmY3T0FwaStzU0k1RlBzT2V2ZWZGVgoybjJHUDg0bHNDTTZ3Y3FLcXRKeStwOC94VEJKdW1MY2RoL1daYktGTDd5YzFGSzdUNXdPVTB3eS9nZ1lVOUVvCk9tT3M3MENQWmloSkNrc1hrd1d0Q0JISEEwWGJPMXpYM1VZdnRpeGMwb2U3aFltd29zZnlQWU1raC9hL2pWYzEKWkhac25wQXZiWTZrVEoyY1dBa1hyS0srVmc5ZGJrWGVPY0FFTnNHazIvcXFxVGNOV1FJREFRQUJNQTBHQ1NxRwpTSWIzRFFFQkN3VUFBNElCQVFDQXZZNzBHVzBTM1V4d01mUHJGYTZvOFJxS3FNSDlCRE9lZ29zZGc5Nm9QakZnClgzRGJjblU5U0QxTzAyZUhNb0RTRldiNFlsK3dwZk9zUDFKekdQTERQcXV0RWRuVjRsbUJlbG15Q09xb0F4R0gKRW1vZGNUSWVxQXBnVDNEaHR1NW90UW4zZTdGaGNRRHhDelN6SldkUTRJTFh4SExsTVBkeHpRN1NwTzVySERGeAo0eEd6dkNHRkMwSlhBZ2w4dFhvR3dUYkpDR1hxYWV2cUIrNXVLY1NpSUo2M2dhQk1USytjUmF5MkR4L1dwcEdBClZWTnJsTWs4TEVQT1VSN2RZMm0xT3RaU1hCckdib3QwQjNEUG9yRkNpeVF5Q20vd0FYMFk0Z0hiMlNmcitOeFoKQkppb2VXajZ6ZGFvU3dPZkwxd2taWlJjVGtlZlZyZXdVRjZRQ3BCcAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + +# The customer supplied private key to use for Apache webtier SSL configuration. +# The value must be a string containing a base64 encoded key. Run following command to get it. +# base64 -i ${SSL_KEY_FILE} | tr -d '\n' +customKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRREtsUm5YZGJLYW9TQWcKVTFUb0tScmdrQ1BXb3pOL0U1cHcwZ3hRa002eDRxTy9jMXVNaWdyY0RUNms1NFBjNzJreW9TcmVySjZJRXdxQgpNUFFNZGpuOFlGWnpFVCs0R3RrejRMeXZMQVJqMEQzSnhhU0RISGtDTWRMbCswclJlSUE0MTZDQkc2MFRSSTIxCitkL3M0Q21MNnhJamtVK3c1Njk1OFZYYWZZWS96aVd3SXpyQnlvcXEwbkw2bnovRk1FbTZZdHgySDlabHNvVXYKdkp6VVVydFBuQTVUVERMK0NCaFQwU2c2WTZ6dlFJOW1LRWtLU3hlVEJhMElFY2NEUmRzN1hOZmRSaSsyTEZ6UwpoN3VGaWJDaXgvSTlneVNIOXIrTlZ6VmtkbXlla0M5dGpxUk1uWnhZQ1Jlc29yNVdEMTF1UmQ0NXdBUTJ3YVRiCitxcXBOdzFaQWdNQkFBRUNnZ0VCQUtPKzR4VnFHRVN1aWxZMnBVSEd2K2ZWK25IcWxweFh6eFQwWTJuWHNvck0KZzhralNGT1AzUGxEWjJoSmppZE9DUDBZa3B0TWNoUFJPRU4ydXowN2J1RlZTV3RXL09jbUpIeXZZalJCWXdiKwo4b0tlVTd4NmprRTgzcGh3aDJoTGUzRDJzZERKK3hyQTViNjZ5OG9lNHRZcTJ3Mk96aGhUSFY1MnVRdVRQS2xpCjJpSHNYQzIwT1dMSmRuMGU1a0IycTJhV3JJaUJBVzI1Y0JyRDQ5MWFyTDh0emJQOWM4eUUyWUdNM1FKaUFtbkYKNUxZUElzZFdVczJYNEhscWtUM0d6ZEVxNUtzV0pzdjN5QUkxOVJ4eXAwZXd1ditTN3hsRjdIZGlhbnR6ZUp4WAp3MnRWbHpjb1BVQVhoVHIxS0N1UDNCT3BQVXNvMG9oaDNzRFVXamVVWUNVQ2dZRUE3L25QYTE5ckpKUExJOFZiCllhQ2pEKzhTR0FvVWZwSDdRTVFyT2RzR0RkcWRKa2VlNEJ0RDBITUEzL1lLVGFUK0JvRVZmQ2czSWpZVWpmeGcKSkp0VWlJVlcya0RsMU5NY0xXaldINExPaFErQlRGbWcvbFlkc2puMW9FbUJ1Rk1NYWF0ejNGdmZscFRCekg4cwpwMHFyL0hJYTFTbllBckVTUXZUVk9MMVhtcThDZ1lFQTJCd1V6NmpQdVVGR3ZKS3RxWTZVbE9yYm05WXFyYVdDCjlhQ3ZBTDFHZ0Q1U1FEcGRVZnl3MVlWdm9hUU9DWHBOL0Z5UHZCdFF2TzYrbHp0MjVTcmMwZk0weHI3d3ZHRmEKSW5FcmlSOXAvMXdXU01yaWFXZitKaE81NENneFZ0alBXZm1pOVNhc0pqOE1jZVk0cUNCNUVJLzM1cjVaa3lFRQozeEhzcEUxVnVuY0NnWUJLYXBveXZzVTM4NGprRDloMW50M1NIQjN0VEhyc2dSSjhGQmtmZU5jWXhybEMzS1RjCjlEZUVWWlZvM2lCMTBYdGd3dmpKcHFMcVBnRUR3c2FCczVWMFBIMGhjMHlTUWVFVUI5V1dzZmFlOXA3dThVQm0KZm9mNDg5WkNuV2pYb3hGUFYzYTNWOW92RlBSQUdSUGMwT0FpaWJQZWRIcGk0MHc1YlRrTnZsR0RTd0tCZ1FESApubWk2eUR2WDZ5dmowN2tGL2VYUkNIK0NHdm1oSEZremVoRXNwYWtSbkg5dFJId2UxMEtnZUhqODNnVDVURGZzCis3THBGbklsa29JS1A2czdVN1JWV2tsTnErSENvRW9adGw5NGNjUC9WSmhnOU1iZWhtaUQwNFRHUVZvUjFvTHgKb1YyZEJQUFBBRDRHbDVtTjh6RGcwNXN4VUhKOUxPckxBa3VNR01NdlVRS0JnQ2RUUGgwVHRwODNUUVZFZnR3bwpuSGVuSEQzMkhrZkR0MTV4Wk84NVZGcTlONVg2MjB2amZKNkNyVnloS1RISllUREs1N2owQ3Z2STBFTksxNytpCi9yaXgwVlFNMTBIMFFuTkZlb0pmS0VITHhXb2czSHVBSVZxTEg4NmJwcytmb25nOCtuMGgvbk5NZUZNYjdSNUMKdmFHNEVkc0VHV0hZS2FiL2lzRlowUVU0Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-samples/default-sample/README.md b/OracleWebCenterPortal/kubernetes/charts/apache-samples/default-sample/README.md new file mode 100644 index 000000000..806bab5c9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-samples/default-sample/README.md @@ -0,0 +1,39 @@ +# Apache load balancer default sample +In this sample, we will configure the Apache webtier as a load balancer for a WebLogic domain using the default configuration. We will demonstrate how to use the Apache webtier to handle traffic to a backend WebLogic domain. + +## 1. Create a WebLogic domain +We need to prepare a backend domain for load balancing by the Apache webtier. Refer to the [sample](/kubernetes/samples/scripts/create-weblogic-domain/domain-home-on-pv/README.md), to create a WebLogic domain. Keep the default values for the following configuration parameters: +- namespace: `default` +- domainUID: `domain1` +- clusterName: `cluster-1` +- adminServerName: `admin-server` +- adminPort: `7001` +- managedServerPort: `8001` + +After the domain is successfully created, deploy the sample web application, `testwebapp.war`, on the domain cluster using the WLS Administration Console. The sample web application is located in the `kubernetes/samples/charts/application` directory. + +## 2. Build the Apache webtier Docker image +Refer to the [sample](https://github.com/oracle/docker-images/tree/master/OracleWebLogic/samples/12213-webtier-apache), to build the Apache webtier Docker image. + +## 3. Install the Apache webtier with a Helm chart +The Apache webtier Helm chart [is located here](../../apache-webtier/README.md). +Install the Apache webtier Helm chart into the default namespace with the default settings: +```shell +$ cd kubernetes/samples/charts +$ helm install my-release apache-webtier +``` + +## 4. Run the sample application +Now you can send request to the WebLogic domain with the unique entry point of Apache. Alternatively, you can access the URL in a web browser. +```shell +$ curl --silent http://${HOSTNAME}:30305/weblogic/testwebapp/ +``` +You can also use an SSL URL to send requests to the WebLogic domain. Access the SSL URL via the `curl` command or a web browser. +```shell +$ curl -k --silent https://${HOSTNAME}:30443/weblogic/testwebapp/ +``` + +## 5. Uninstall the Apache webtier +```shell +$ helm uninstall my-release +``` diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/Chart.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/Chart.yaml new file mode 100644 index 000000000..413b8ba2d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/Chart.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +apiVersion: v1 +name: apache-webtier +version: 1.0.0 +appVersion: 12.2.1.3 +description: Chart for Apache HTTP Server +keywords: +- apache +- http +- https +- load balance +- proxy +home: https://httpd.apache.org +sources: +- https://github.com/oracle/weblogic-kubernetes-operator/tree/master/kubernetes/samples/charts/apache-webtier +maintainers: +- name: Oracle +engine: gotpl diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/README.md b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/README.md new file mode 100644 index 000000000..2be875dd3 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/README.md @@ -0,0 +1,92 @@ +# Apache webtier Helm chart + +This Helm chart bootstraps an Apache HTTP Server deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +The chart depends on the Docker image for the Apache HTTP Server with Oracle WebLogic Server Proxy Plugin (supported versions 12.2.1.3.0 and 12.2.1.4.0). See the details in [Apache HTTP Server with Oracle WebLogic Server Proxy Plugin on Docker](https://github.com/oracle/docker-images/tree/master/OracleWebLogic/samples/12213-webtier-apache). + +## Prerequisites + +You will need to build a Docker image with the Apache webtier in it using the sample provided [here](https://github.com/oracle/docker-images/tree/master/OracleWebLogic/samples/12213-webtier-apache) +in order to use this load balancer. + +## Installing the Chart +To install the chart with the release name `my-release`: +```shell +$ helm install my-release apache-webtier +``` +The command deploys the Apache HTTP Server on the Kubernetes cluster with the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Uninstalling the Chart + +To uninstall/delete `my-release`: + +```shell +$ helm uninstall my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Configuration + +The following table lists the configurable parameters of the Apache webtier chart and their default values. + + +| Parameter | Description | Default | +| -----------------------------------| ------------------------------------------------------------- | ----------------------| +| `image` | Apache webtier Docker image | `oracle/apache:12.2.1.3` | +| `imagePullPolicy` | Image pull policy for the Apache webtier Docker image | `IfNotPresent` | +| `imagePullSecrets` | Image pull Secrets required to access the registry containing the Apache webtier Docker image| ``| +| `persistentVolumeClaimName` | Persistence Volume Claim name Apache webtier | `` | +| `createRBAC` | Boolean indicating if RBAC resources should be created | `true` | +| `httpNodePort` | Node port to expose for HTTP access | `30305` | +| `httpsNodePort` | Node port to expose for HTTPS access | `30443` | +| `virtualHostName` | The `VirtualHostName` of the Apache HTTP Server | `` | +| `customCert` | The customer supplied certificate | `` | +| `customKey` | The customer supplied private key | `` | +| `domainUID` | Unique ID identifying a domain | `domain1` | +| `clusterName` | Cluster name | `cluster-1` | +| `adminServerName` | Name of the Administration Server | `admin-server` | +| `adminPort` | Port number for Administration Server | `7001` | +| `managedServerPort` | Port number for each Managed Server | `8001` | +| `location` | Prepath for all applications deployed on the WebLogic cluster | `/weblogic` | +| `useNonPriviledgedPorts` | Configuration of Apache webtier on NonPriviledgedPort | `false` | + + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example: + +```shell +$ helm install my-release --set persistentVolumeClaimName=webtier-apache-pvc apache-webtier +``` + +Alternatively, a YAML file that specifies the values for the parameters can be provided while +installing the chart. For example: + +```shell +$ helm install my-release --values values.yaml apache-webtier +``` +## useNonPriviledgedPorts +By default, the chart will install the Apache webtier on PriviledgedPort (port 80). Set the flag `useNonPriviledgedPorts=true` to enable the Apache webtier to listen on port `8080` + + +## RBAC +By default, the chart will install the recommended RBAC roles and role bindings. + +Set the flag `--authorization-mode=RBAC` on the API server. See the following document for how to enable [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/). + +To determine if your cluster supports RBAC, run the following command: + +```shell +$ kubectl api-versions | grep rbac +``` + +If the output contains "beta", you may install the chart with RBAC enabled. + +### Disable RBAC role/rolebinding creation + +To disable the creation of RBAC resources (on clusters with RBAC). Do the following: + +```shell +$ helm install my-release apache-webtier --set createRBAC=false +``` diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/_helpers.tpl b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/_helpers.tpl new file mode 100644 index 000000000..c7999d287 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/_helpers.tpl @@ -0,0 +1,25 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "apache.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "apache.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "apache.serviceAccountName" -}} +{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 -}} +{{- end -}} diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/cluster-role-binding.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/cluster-role-binding.yaml new file mode 100644 index 000000000..188e54d1a --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/cluster-role-binding.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{ if .Values.createRBAC }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "apache.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "apache.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ template "apache.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} +{{ end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/cluster-role.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/cluster-role.yaml new file mode 100644 index 000000000..449a87664 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/cluster-role.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{ if .Values.createRBAC }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "apache.fullname" . }} +rules: + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + - secrets + verbs: + - get + - list + - watch + - apiGroups: + - extensions + resources: + - ingresses + verbs: + - get + - list + - watch +{{ end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/deployment.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/deployment.yaml new file mode 100644 index 000000000..cd7b07ad3 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/deployment.yaml @@ -0,0 +1,106 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +kind: Deployment +apiVersion: apps/v1 +metadata: + name: {{ template "apache.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "apache.fullname" . }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ template "apache.fullname" . }} + template: + metadata: + labels: + app: {{ template "apache.fullname" . }} + spec: + serviceAccountName: {{ template "apache.serviceAccountName" . }} + terminationGracePeriodSeconds: 60 +{{- if or (and (.Values.virtualHostName) (.Values.customCert)) (.Values.persistentVolumeClaimName) }} + volumes: +{{- end }} +{{- if and (.Values.virtualHostName) (.Values.customCert) }} + - name: serving-cert + secret: + defaultMode: 420 + secretName: {{ template "apache.fullname" . }}-cert +{{- end }} +{{- if .Values.persistentVolumeClaimName }} + - name: {{ template "apache.fullname" . }} + persistentVolumeClaim: + claimName: {{ .Values.persistentVolumeClaimName | quote }} +{{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ .Values.imagePullSecrets | toYaml }} + {{- end }} + containers: + - name: {{ template "apache.fullname" . }} + image: {{ .Values.image | quote }} + imagePullPolicy: {{ .Values.imagePullPolicy | quote }} +{{- if or (and (.Values.virtualHostName) (.Values.customCert)) (.Values.persistentVolumeClaimName) }} + volumeMounts: +{{- end }} +{{- if and (.Values.virtualHostName) (.Values.customCert) }} + - name: serving-cert + mountPath: "/var/serving-cert" +{{- end }} +{{- if .Values.persistentVolumeClaimName }} + - name: {{ template "apache.fullname" . }} + mountPath: "/config" +{{- end }} +{{- if or (not (.Values.persistentVolumeClaimName)) (.Values.virtualHostName) }} + env: +{{- end }} +{{- if .Values.useNonPriviledgedPorts }} + - name: NonPriviledgedPorts + value: "true" +{{- end }} +{{- if not (.Values.persistentVolumeClaimName) }} + - name: WEBLOGIC_CLUSTER + value: "{{ .Values.domainUID | replace "_" "-" | lower }}-cluster-{{ .Values.clusterName | replace "_" "-" | lower }}:{{ .Values.managedServerPort }}" + - name: LOCATION + value: {{ .Values.location | quote }} + - name: WEBLOGIC_HOST + value: "{{ .Values.domainUID | replace "_" "-" | lower }}-{{ .Values.adminServerName | replace "_" "-" | lower }}" + - name: WEBLOGIC_PORT + value: {{ .Values.adminPort | quote }} +{{- end }} +{{- if .Values.virtualHostName }} + - name: VIRTUAL_HOST_NAME + value: {{ .Values.virtualHostName | quote }} +{{- if .Values.customCert }} + - name: SSL_CERT_FILE + value: "/var/serving-cert/tls.crt" + - name: SSL_CERT_KEY_FILE + value: "/var/serving-cert/tls.key" +{{- end }} +{{- end }} + readinessProbe: + tcpSocket: +{{- if .Values.useNonPriviledgedPorts }} + port: 8080 +{{- else }} + port: 80 +{{- end }} + failureThreshold: 1 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + livenessProbe: + tcpSocket: +{{- if .Values.useNonPriviledgedPorts }} + port: 8080 +{{- else }} + port: 80 +{{- end }} + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/secret.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/secret.yaml new file mode 100644 index 000000000..bb716f50b --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/secret.yaml @@ -0,0 +1,14 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{ if .Values.customCert }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "apache.fullname" . }}-cert + namespace: {{ .Release.Namespace | quote }} +type: Opaque +data: + tls.crt: {{ .Values.customCert | quote }} + tls.key: {{ .Values.customKey | quote }} +{{ end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/service-account.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/service-account.yaml new file mode 100644 index 000000000..f76d46aec --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/service-account.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "apache.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/service.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/service.yaml new file mode 100644 index 000000000..c8b8089eb --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/templates/service.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "apache.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +spec: + type: NodePort + selector: + app: {{ template "apache.fullname" . }} + ports: +{{- if .Values.useNonPriviledgedPorts }} + - port: 8080 +{{- else}} + - port: 80 +{{- end }} + nodePort: {{ .Values.httpNodePort }} + name: http +{{- if .Values.virtualHostName }} + - port: 4433 +{{- else }} + - port: 443 +{{- end }} + nodePort: {{ .Values.httpsNodePort }} + name: https + diff --git a/OracleWebCenterPortal/kubernetes/charts/apache-webtier/values.yaml b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/values.yaml new file mode 100644 index 000000000..ee0a8a815 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/apache-webtier/values.yaml @@ -0,0 +1,79 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# Apache webtier docker image +image: "oracle/apache:12.2.1.3" + +# imagePullPolicy specifies the image pull policy for the apache webiter docker image +imagePullPolicy: "IfNotPresent" + +# imagePullSecrets contains an optional list of Kubernetes secrets, that are needed +# to access the registry containing the apache webtier image. +# If no secrets are required, then omit this property. +# +# Example : a secret is needed, and has been stored in 'my-apache-webtier-secret' +# +# imagePullSecrets: +# - name: my-apache-webtier-secret +# +# imagePullSecrets: +# - name: + +# Volume path for Apache webtier. By default, it is empty, which causes the volume +# mount be disabled and, therefore, the built-in Apache plugin config be used. +# Use this to provide your own Apache webtier configuration as needed; simply define this +# path and put your own custom_mod_wl_apache.conf file under this path. +persistentVolumeClaimName: + +# Boolean indicating if RBAC resources should be created +createRBAC: true + +# NodePort to expose for http access +httpNodePort: 30305 + +# NodePort to expose for https access +httpsNodePort: 30443 + +# The VirtualHostName of the Apache HTTP server. It is used to enable custom SSL configuration. +# If it is set, the Apache HTTP Server is configured to listen to port 4433 for SSL traffic. +virtualHostName: + +# The customer supplied certificate to use for Apache webtier SSL configuration. +# The value must be a string containing a base64 encoded certificate. +# If 'virtualHostName' is set, the custom certificate and private key are not provided, +# the default built-in auto-generated sample certificate and private key in the apache image will be used. +# This parameter is ignored if 'virtualHostName' is not set. +customCert: + +# The customer supplied private key to use for Apache webtier SSL configuration. +# The value must be a string containing a base64 encoded key. +# If 'virtualHostName' is set, the custom certificate and private key are not provided, +# the default built-in auto-generated sample certificate and private key in the apache image will be used. +# This parameter is ignored if 'virtualHostName' is not set. +customKey: + +# Unique ID identifying a domain. +# This ID must not contain an underscore ("_"), and must be lowercase and unique across all domains in a Kubernetes cluster. +domainUID: "domain1" + +# Cluster name +clusterName: "cluster-1" + +# Name of the admin server +adminServerName: "admin-server" + +# Port number for admin server +adminPort: 7001 + +# Port number for each managed server +managedServerPort: 8001 + +# Prepath for all application deployed on WebLogic cluster. +# For example, if it is set to '/weblogic', all applications deployed on the cluster can be accessed via +# http://myhost:myport/weblogic/application_end_url +# where 'myhost' is the IP of the machine that runs the Apache web tier, and +# 'myport' is the port that the Apache web tier is publicly exposed to. +location: "/weblogic" + +# Use non privileged port 8080 to listen. If set to false, default privileged port 80 will be used. +useNonPriviledgedPorts: false diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/Chart.yaml b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/Chart.yaml old mode 100755 new mode 100644 similarity index 80% rename from OracleWebCenterPortal/kubernetes/ingress-per-domain/Chart.yaml rename to OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/Chart.yaml index b42d4f9fa..dc3981291 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/Chart.yaml +++ b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/Chart.yaml @@ -1,6 +1,6 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - +# apiVersion: v1 appVersion: "1.0" description: A Helm chart to create an Ingress for a WLS domain. diff --git a/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/nginx-ingress-k8s1.19.yaml b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/nginx-ingress-k8s1.19.yaml new file mode 100644 index 000000000..ea79521df --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/nginx-ingress-k8s1.19.yaml @@ -0,0 +1,101 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +{{- if eq .Values.type "NGINX" }} +{{- if or (eq .Values.sslType "NONSSL") (eq .Values.sslType "SSL") }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Values.wlsDomain.domainUID }}-nginx + namespace: {{ .Release.Namespace }} + annotations: + kubernetes.io/ingress.class: 'nginx' + nginx.ingress.kubernetes.io/proxy-connect-timeout: '{{ .Values.nginx.connectTimeout }}' + nginx.ingress.kubernetes.io/proxy-read-timeout: '{{ .Values.nginx.readTimeout }}' + nginx.ingress.kubernetes.io/proxy-send-timeout: '{{ .Values.nginx.sendTimeout }}' + nginx.ingress.kubernetes.io/affinity: 'cookie' + nginx.ingress.kubernetes.io/session-cookie-name: 'stickyid' + nginx.ingress.kubernetes.io/session-cookie-expires: '{{ .Values.nginx.cookieExpires }}' + nginx.ingress.kubernetes.io/session-cookie-max-age: '{{ .Values.nginx.cookieMaxAge }}' + nginx.ingress.kubernetes.io/ssl-redirect: 'false' + nginx.ingress.kubernetes.io/affinity-mode: 'persistent' +{{- if eq .Values.sslType "SSL" }} + nginx.ingress.kubernetes.io/configuration-snippet: | + more_set_input_headers "X-Forwarded-Proto: https"; + more_set_input_headers "WL-Proxy-SSL: true"; + nginx.ingress.kubernetes.io/ingress.allow-http: 'false' +{{- end }} +spec: + rules: + - host: '{{ .Values.nginx.hostname }}' + http: + paths: + - path: /webcenter + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /console + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.adminServerPort }} + - path: /rsscrawl + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /webcenterhelp + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /rest + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /em + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /wsrp-tools + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpPortletClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpPortletManagedServerPort }} + - path: /portalTools + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpPortletClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpPortletManagedServerPort }} +{{- if eq .Values.sslType "SSL" }} + tls: + - hosts: + - '{{ .Values.nginx.hostname }}' + secretName: {{ .Values.wlsDomain.domainUID }}-tls-cert +{{- end }} + +{{- end }} +{{- end }} +{{- end }} + diff --git a/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/nginx-ingress.yaml b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/nginx-ingress.yaml new file mode 100644 index 000000000..41917e342 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/nginx-ingress.yaml @@ -0,0 +1,77 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +{{- if semverCompare "<1.19-0" .Capabilities.KubeVersion.GitVersion -}} +{{- if eq .Values.type "NGINX" }} +{{- if or (eq .Values.sslType "NONSSL") (eq .Values.sslType "SSL") }} +--- +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ .Values.wlsDomain.domainUID }}-nginx + namespace: {{ .Release.Namespace }} + annotations: + kubernetes.io/ingress.class: 'nginx' + nginx.ingress.kubernetes.io/proxy-connect-timeout: '{{ .Values.nginx.connectTimeout }}' + nginx.ingress.kubernetes.io/proxy-read-timeout: '{{ .Values.nginx.readTimeout }}' + nginx.ingress.kubernetes.io/proxy-send-timeout: '{{ .Values.nginx.sendTimeout }}' + nginx.ingress.kubernetes.io/affinity: 'cookie' + nginx.ingress.kubernetes.io/session-cookie-name: 'stickyid' + nginx.ingress.kubernetes.io/session-cookie-expires: '{{ .Values.nginx.cookieExpires }}' + nginx.ingress.kubernetes.io/session-cookie-max-age: '{{ .Values.nginx.cookieMaxAge }}' + nginx.ingress.kubernetes.io/ssl-redirect: 'false' + nginx.ingress.kubernetes.io/affinity-mode: 'persistent' +{{- if eq .Values.sslType "SSL" }} + nginx.ingress.kubernetes.io/configuration-snippet: | + more_set_input_headers "X-Forwarded-Proto: https"; + more_set_input_headers "WL-Proxy-SSL: true"; + nginx.ingress.kubernetes.io/ingress.allow-http: 'false' +{{- end }} +spec: + rules: + - host: '{{ .Values.nginx.hostname }}' + http: + paths: + - path: /webcenter + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /console + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.adminServerPort }} + - path: /rsscrawl + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /webcenterhelp + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /rest + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /em + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /wsrp-tools + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpPortletClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpPortletManagedServerPort }} + - path: /portalTools + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpPortletClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpPortletManagedServerPort }} +{{- if eq .Values.sslType "SSL" }} + tls: + - hosts: + - '{{ .Values.nginx.hostname }}' + secretName: {{ .Values.wlsDomain.domainUID }}-tls-cert +{{- end }} + +{{- end }} +{{- end }} +{{- end }} + diff --git a/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/traefik-ingress-k8s1.19.yaml b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/traefik-ingress-k8s1.19.yaml new file mode 100644 index 000000000..1965ccd59 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/traefik-ingress-k8s1.19.yaml @@ -0,0 +1,110 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +{{- if eq .Values.type "TRAEFIK" }} +{{- if or (eq .Values.sslType "NONSSL") (eq .Values.sslType "SSL") }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Values.wlsDomain.domainUID }}-traefik + namespace: {{ .Release.Namespace }} + labels: + weblogic.resourceVersion: domain-v2 + annotations: + kubernetes.io/ingress.class: 'traefik' +{{- if eq .Values.sslType "SSL" }} + traefik.ingress.kubernetes.io/router.entrypoints: 'websecure' + traefik.ingress.kubernetes.io/router.tls: 'true' + traefik.ingress.kubernetes.io/router.middlewares: '{{ .Release.Namespace}}-wls-proxy-ssl@kubernetescrd' +{{- end }} +spec: + rules: + - host: '{{ .Values.traefik.hostname }}' + http: + paths: + - path: /webcenter + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /console + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.adminServerPort }} + - path: /rsscrawl + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /webcenterhelp + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /rest + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /em + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /wsrp-tools + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpPortletClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpPortletManagedServerPort }} + - path: /portalTools + pathType: ImplementationSpecific + backend: + service: + name: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpPortletClusterName | lower | replace "_" "-" }}' + port: + number: {{ .Values.wlsDomain.wcpPortletManagedServerPort }} +{{- if eq .Values.sslType "SSL" }} + tls: + - hosts: + - '{{ .Values.traefik.hostname }}' + secretName: {{ .Values.wlsDomain.domainUID }}-tls-cert +{{- end }} +--- +#Create Traefik Middleware custom resource for SSL Termination +{{- if eq .Values.sslType "SSL" }} +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: wls-proxy-ssl + namespace: {{ .Release.Namespace }} +spec: + headers: + customRequestHeaders: + X-Custom-Request-Header: "" + X-Forwarded-For: "" + WL-Proxy-Client-IP: "" + WL-Proxy-SSL: "" + WL-Proxy-SSL: "true" + sslRedirect: true +{{- end }} + +{{- end }} +{{- end }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/traefik-ingress.yaml b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/traefik-ingress.yaml new file mode 100644 index 000000000..3a4df423c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/templates/traefik-ingress.yaml @@ -0,0 +1,87 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +{{- if semverCompare "<1.19-0" .Capabilities.KubeVersion.GitVersion -}} +{{- if eq .Values.type "TRAEFIK" }} +{{- if or (eq .Values.sslType "NONSSL") (eq .Values.sslType "SSL") }} +--- +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ .Values.wlsDomain.domainUID }}-traefik + namespace: {{ .Release.Namespace }} + labels: + weblogic.resourceVersion: domain-v2 + annotations: + kubernetes.io/ingress.class: 'traefik' +{{- if eq .Values.sslType "SSL" }} + traefik.ingress.kubernetes.io/router.entrypoints: 'websecure' + traefik.ingress.kubernetes.io/router.tls: 'true' + traefik.ingress.kubernetes.io/router.middlewares: '{{ .Release.Namespace}}-wls-proxy-ssl@kubernetescrd' +{{- end }} +spec: + rules: + - host: '{{ .Values.traefik.hostname }}' + http: + paths: + - path: /webcenter + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /console + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.adminServerPort }} + - path: /rsscrawl + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /webcenterhelp + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /rest + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /em + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpManagedServerPort }} + - path: /wsrp-tools + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpPortletClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpPortletManagedServerPort }} + - path: /portalTools + backend: + serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.wcpPortletClusterName | lower | replace "_" "-" }}' + servicePort: {{ .Values.wlsDomain.wcpPortletManagedServerPort }} +{{- if eq .Values.sslType "SSL" }} + tls: + - hosts: + - '{{ .Values.traefik.hostname }}' + secretName: {{ .Values.wlsDomain.domainUID }}-tls-cert +{{- end }} +--- +#Create Traefik Middleware custom resource for SSL Termination +{{- if eq .Values.sslType "SSL" }} +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: wls-proxy-ssl + namespace: {{ .Release.Namespace }} +spec: + headers: + customRequestHeaders: + X-Custom-Request-Header: "" + X-Forwarded-For: "" + WL-Proxy-Client-IP: "" + WL-Proxy-SSL: "" + WL-Proxy-SSL: "true" + sslRedirect: true +{{- end }} + +{{- end }} +{{- end }} +{{- end }} + diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/nginx-tls.yaml b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/tls/nginx-tls.yaml old mode 100755 new mode 100644 similarity index 89% rename from OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/nginx-tls.yaml rename to OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/tls/nginx-tls.yaml index e34c0bcd9..3024b9349 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/nginx-tls.yaml +++ b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/tls/nginx-tls.yaml @@ -12,7 +12,7 @@ spec: tls: - hosts: - domain1.org - secretName: domain1-tls-cert + secretName: wcp-domain-tls-cert rules: - host: domain1.org http: @@ -20,6 +20,6 @@ spec: - path: backend: serviceName: wcp-domain-cluster-wcp-cluster - servicePort: 8889 + servicePort: 8788 diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/traefik-tls.yaml b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/tls/traefik-tls.yaml old mode 100755 new mode 100644 similarity index 96% rename from OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/traefik-tls.yaml rename to OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/tls/traefik-tls.yaml index 96d51a5ab..636b07073 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/traefik-tls.yaml +++ b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/tls/traefik-tls.yaml @@ -13,7 +13,7 @@ spec: - match: HostSNI(`wcp-domain.example.org`) services: - name: wcp-domain-cluster-wcp-cluster - port: 8889 + port: 8788 weight: 3 TerminationDelay: 400 tls: diff --git a/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/values.yaml b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/values.yaml new file mode 100644 index 000000000..9678cc41d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/ingress-per-domain/values.yaml @@ -0,0 +1,43 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# +# Default values for ingress-per-domain. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +# +# Load balancer type. Supported values are: TRAEFIK, NGINX +type: TRAEFIK + +# Type of Configuration Supported Values are : NONSSL, SSL +sslType: NONSSL + +# domainType Supported values are soa,osb and soaosb. +domainType: wcp + +#WLS domain as backend to the load balancer +wlsDomain: + domainUID: wcp-domain + adminServerName: adminserver + adminServerPort: 7001 + adminServerSSLPort: + wcpClusterName: wcp-cluster + wcpManagedServerPort: 8888 + wcpManagedServerSSLPort: + wcpPortletClusterName: wcportlet-cluster + wcpPortletManagedServerPort: 8889 + wcpPortletManagedServerSSLPort: + +# Host specific values +traefik: + hostname: domain1.org + +# Ngnix specific values +nginx: + connectTimeout: 1800 + readTimeout: 1800 + sendTimeout: 1800 + cookieExpires: 172800 + cookieMaxAge: 172800 + + diff --git a/OracleWebCenterPortal/kubernetes/charts/traefik/values.yaml b/OracleWebCenterPortal/kubernetes/charts/traefik/values.yaml index 3acc04e5a..e94bf24f2 100755 --- a/OracleWebCenterPortal/kubernetes/charts/traefik/values.yaml +++ b/OracleWebCenterPortal/kubernetes/charts/traefik/values.yaml @@ -1,34 +1,52 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. -image: - name: traefik - tag: 2.2.8 - pullPolicy: IfNotPresent -ingressRoute: - dashboard: - enabled: true - annotations: {} - labels: {} -providers: - kubernetesCRD: - enabled: true - kubernetesIngress: - enabled: true -ports: - traefik: - port: 9000 - expose: true - exposedPort: 9000 - protocol: TCP - web: - port: 8000 - expose: true - exposedPort: 30305 - nodePort: 30305 - protocol: TCP - websecure: - port: 8443 - expose: true - exposedPort: 30443 - protocol: TCP - nodePort: 30443 \ No newline at end of file +# +image: + name: traefik + tag: 2.2.8 + pullPolicy: IfNotPresent +ingressRoute: + dashboard: + enabled: true + # Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) + annotations: {} + # Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) + labels: {} +providers: + kubernetesCRD: + enabled: true + kubernetesIngress: + enabled: true + # IP used for Kubernetes Ingress endpoints +ports: + traefik: + port: 9000 + expose: true + # The exposed port for this service + exposedPort: 9000 + # The port protocol (TCP/UDP) + protocol: TCP + web: + port: 8000 + # hostPort: 8000 + expose: true + exposedPort: 30305 + nodePort: 30305 + # The port protocol (TCP/UDP) + protocol: TCP + # Use nodeport if set. This is useful if you have configured Traefik in a + # LoadBalancer + # nodePort: 32080 + # Port Redirections + # Added in 2.2, you can make permanent redirects via entrypoints. + # https://docs.traefik.io/routing/entrypoints/#redirection + # redirectTo: websecure + websecure: + port: 8443 +# # hostPort: 8443 + expose: true + exposedPort: 30443 + # The port protocol (TCP/UDP) + protocol: TCP + nodePort: 30443 + diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/.helmignore b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/.helmignore new file mode 100644 index 000000000..1397cc19f --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/.helmignore @@ -0,0 +1,12 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +.git/ +.gitignore +*.bak +*.tmp +*.orig +*~ +.project +.idea/ diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/Chart.yaml b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/Chart.yaml new file mode 100644 index 000000000..b5cac770e --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/Chart.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +apiVersion: v1 +name: weblogic-operator +description: Helm chart for configuring the WebLogic operator. + +type: application +version: 3.3.0 +appVersion: 3.3.0 diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_domain-namespaces.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_domain-namespaces.tpl new file mode 100644 index 000000000..08988c28d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_domain-namespaces.tpl @@ -0,0 +1,134 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.domainNamespaces" }} +{{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +{{- $args := include "utils.cloneDictionary" . | fromYaml -}} +{{- $key := .Release.Namespace -}} +{{- $ignore := set $args "domainNamespace" $key -}} +{{- include "operator.operatorRoleBindingNamespace" $args -}} +{{- else if eq (default "List" .domainNamespaceSelectionStrategy) "List" }} +{{- $args := include "utils.cloneDictionary" . | fromYaml -}} +{{- range $key := $args.domainNamespaces -}} +{{- $ignore := set $args "domainNamespace" $key -}} +{{- include "operator.operatorRoleBindingNamespace" $args -}} +{{- end }} +{{- else if eq .domainNamespaceSelectionStrategy "LabelSelector" }} +{{- $args := include "utils.cloneDictionary" . | fromYaml -}} +{{- /* + Split terms on commas not contained in parentheses. Unfortunately, the regular expression + support included with Helm templates does not include lookarounds. +*/ -}} +{{- $working := dict "rejected" (list) "terms" (list $args.domainNamespaceLabelSelector) }} +{{- if contains "," $args.domainNamespaceLabelSelector }} +{{- $cs := regexSplit "," $args.domainNamespaceLabelSelector -1 }} +{{- $ignore := set $working "st" (list) }} +{{- $ignore := set $working "item" "" }} +{{- range $c := $cs }} +{{- if and (contains "(" $c) (not (contains ")" $c)) }} +{{- $ignore := set $working "item" (print $working.item $c) }} +{{- else if not (eq $working.item "") }} +{{- $ignore := set $working "st" (append $working.st (print $working.item "," $c)) }} +{{- if contains ")" $c }} +{{- $ignore := set $working "item" "" }} +{{- end }} +{{- else }} +{{- $ignore := set $working "st" (append $working.st $c) }} +{{- end }} +{{- end }} +{{- $ignore := set $working "terms" $working.st }} +{{- end }} +{{- $namespaces := (lookup "v1" "Namespace" "" "").items }} +{{- range $t := $working.terms }} +{{- $term := trim $t }} +{{- range $index, $namespace := $namespaces }} +{{- /* + Label selector patterns + Equality-based: =, ==, != + Set-based: x in (a, b), x notin (a, b) + Existence: x, !x +*/ -}} +{{- if not $namespace.metadata.labels }} +{{- $ignore := set $namespace.metadata "labels" (dict) }} +{{- end }} +{{- if hasPrefix "!" $term }} +{{- if hasKey $namespace.metadata.labels (trimPrefix "!" $term) }} +{{- $ignore := set $working "rejected" (append $working.rejected $namespace.metadata.name) }} +{{- end }} +{{- else if contains "!=" $term }} +{{- $split := regexSplit "!=" $term 2 }} +{{- $key := nospace (first $split) }} +{{- if hasKey $namespace.metadata.labels $key }} +{{- if eq (last $split | nospace) (get $namespace.metadata.labels $key) }} +{{- $ignore := set $working "rejected" (append $working.rejected $namespace.metadata.name) }} +{{- end }} +{{- end }} +{{- else if contains "==" $term }} +{{- $split := regexSplit "==" $term 2 }} +{{- $key := nospace (first $split) }} +{{- if or (not (hasKey $namespace.metadata.labels $key)) (not (eq (last $split | nospace) (get $namespace.metadata.labels $key))) }} +{{- $ignore := set $working "rejected" (append $working.rejected $namespace.metadata.name) }} +{{- end }} +{{- else if contains "=" $term }} +{{- $split := regexSplit "=" $term 2 }} +{{- $key := nospace (first $split) }} +{{- if or (not (hasKey $namespace.metadata.labels $key)) (not (eq (last $split | nospace) (get $namespace.metadata.labels $key))) }} +{{- $ignore := set $working "rejected" (append $working.rejected $namespace.metadata.name) }} +{{- end }} +{{- else if contains " notin " $term }} +{{- $split := regexSplit " notin " $term 2 }} +{{- $key := nospace (first $split) }} +{{- if hasKey $namespace.metadata.labels $key }} +{{- $second := nospace (last $split) }} +{{- $parenContents := substr 1 (int (sub (len $second) 1)) $second }} +{{- $values := regexSplit "," $parenContents -1 }} +{{- range $value := $values }} +{{- if eq ($value | nospace) (get $namespace.metadata.labels $key) }} +{{- $ignore := set $working "rejected" (append $working.rejected $namespace.metadata.name) }} +{{- end }} +{{- end }} +{{- end }} +{{- else if contains " in " $term }} +{{- $split := regexSplit " in " $term 2 }} +{{- $key := nospace (first $split) }} +{{- if not (hasKey $namespace.metadata.labels $key) }} +{{- $ignore := set $working "rejected" (append $working.rejected $namespace.metadata.name) }} +{{- else }} +{{- $second := nospace (last $split) }} +{{- $parenContents := substr 1 (int (sub (len $second) 1)) $second }} +{{- $values := regexSplit "," $parenContents -1 }} +{{- $ignore := set $working "found" false }} +{{- range $value := $values }} +{{- if eq ($value | nospace) (get $namespace.metadata.labels $key) }} +{{- $ignore := set $working "found" true }} +{{- end }} +{{- end }} +{{- if not $working.found }} +{{- $ignore := set $working "rejected" (append $working.rejected $namespace.metadata.name) }} +{{- end }} +{{- end }} +{{- else }} +{{- if not (hasKey $namespace.metadata.labels $term) }} +{{- $ignore := set $working "rejected" (append $working.rejected $namespace.metadata.name) }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- range $index, $namespace := $namespaces }} +{{- $key := $namespace.metadata.name -}} +{{- if not (has $key $working.rejected) }} +{{- $ignore := set $args "domainNamespace" $key -}} +{{- include "operator.operatorRoleBindingNamespace" $args -}} +{{- end }} +{{- end }} +{{- else if eq .domainNamespaceSelectionStrategy "RegExp" }} +{{- $args := include "utils.cloneDictionary" . | fromYaml -}} +{{- range $index, $namespace := (lookup "v1" "Namespace" "" "").items }} +{{- if regexMatch $args.domainNamespaceRegExp $namespace.metadata.name }} +{{- $key := $namespace.metadata.name -}} +{{- $ignore := set $args "domainNamespace" $key -}} +{{- include "operator.operatorRoleBindingNamespace" $args -}} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-domain-admin.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-domain-admin.tpl new file mode 100644 index 000000000..94cab9df7 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-domain-admin.tpl @@ -0,0 +1,40 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorClusterRoleDomainAdmin" }} +--- +{{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +kind: "Role" +{{- else }} +kind: "ClusterRole" +{{- end }} +apiVersion: "rbac.authorization.k8s.io/v1" +metadata: + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + name: "weblogic-operator-role-domain-admin" + namespace: {{ .Release.Namespace | quote }} + {{- else }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrole-domain-admin" | join "-" | quote }} + {{- end }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] +- apiGroups: [""] + resources: ["secrets", "pods", "events"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["pods/log"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["pods/exec"] + verbs: ["get", "create"] +- apiGroups: ["weblogic.oracle"] + resources: ["domains"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] +- apiGroups: ["weblogic.oracle"] + resources: ["domains/status"] + verbs: ["get", "watch"] +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-general.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-general.tpl new file mode 100644 index 000000000..2eba13b95 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-general.tpl @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorClusterRoleGeneral" }} +--- +{{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +kind: "Role" +{{- else }} +kind: "ClusterRole" +{{- end }} +apiVersion: "rbac.authorization.k8s.io/v1" +metadata: + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + name: "weblogic-operator-role-general" + namespace: {{ .Release.Namespace | quote }} + {{- else }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrole-general" | join "-" | quote }} + {{- end }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +rules: +{{- if not (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +- apiGroups: [""] + resources: ["namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch", "create", "update", "patch"] +{{- end }} +- apiGroups: ["weblogic.oracle"] + resources: ["domains", "domains/status"] + verbs: ["get", "list", "watch", "update", "patch"] +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["selfsubjectrulesreviews"] + verbs: ["create"] +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-namespace.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-namespace.tpl new file mode 100644 index 000000000..6310779bb --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-namespace.tpl @@ -0,0 +1,40 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorClusterRoleNamespace" }} +--- +{{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +kind: "Role" +{{- else }} +kind: "ClusterRole" +{{- end }} +apiVersion: "rbac.authorization.k8s.io/v1" +metadata: + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + name: "weblogic-operator-role-namespace" + namespace: {{ .Release.Namespace | quote }} + {{- else }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrole-namespace" | join "-" | quote }} + {{- end }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +rules: +- apiGroups: [""] + resources: ["services", "configmaps", "pods", "events"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["pods/log"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["pods/exec"] + verbs: ["get", "create"] +- apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] +- apiGroups: ["policy"] + resources: ["poddisruptionbudgets"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-nonresource.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-nonresource.tpl new file mode 100644 index 000000000..e3b6a2785 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-nonresource.tpl @@ -0,0 +1,15 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorClusterRoleNonResource" }} +--- +kind: "ClusterRole" +apiVersion: "rbac.authorization.k8s.io/v1" +metadata: + name: {{ list .Release.Namespace "weblogic-operator-clusterrole-nonresource" | join "-" | quote }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +rules: +- nonResourceURLs: ["/version/*"] + verbs: ["get"] +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-operator-admin.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-operator-admin.tpl new file mode 100644 index 000000000..46faed184 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-operator-admin.tpl @@ -0,0 +1,34 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorClusterRoleOperatorAdmin" }} +--- +{{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +kind: "Role" +{{- else }} +kind: "ClusterRole" +{{- end }} +apiVersion: "rbac.authorization.k8s.io/v1" +metadata: + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + name: "weblogic-operator-role-operator-admin" + namespace: {{ .Release.Namespace | quote }} + {{- else }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrole-operator-admin" | join "-" | quote }} + {{- end }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +rules: +- apiGroups: [""] + resources: ["configmaps", "secrets"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] +- apiGroups: [""] + resources: ["pods", "events"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["pods/log"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["pods/exec"] + verbs: ["get", "create"] +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-auth-delegator.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-auth-delegator.tpl new file mode 100644 index 000000000..783f970e7 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-auth-delegator.tpl @@ -0,0 +1,30 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.clusterRoleBindingAuthDelegator" }} +--- +apiVersion: "rbac.authorization.k8s.io/v1" +{{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +kind: "RoleBinding" +{{- else }} +kind: "ClusterRoleBinding" +{{- end }} +metadata: + labels: + weblogic.operatorName: {{ .Release.Namespace | quote}} + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + name: "weblogic-operator-rolebinding-auth-delegator" + namespace: {{ .Release.Namespace | quote }} + {{- else }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrolebinding-auth-delegator" | join "-" | quote }} + {{- end }} +roleRef: + apiGroup: "rbac.authorization.k8s.io" + kind: "ClusterRole" + name: "system:auth-delegator" +subjects: +- kind: "ServiceAccount" + apiGroup: "" + name: {{ .serviceAccount | quote }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-discovery.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-discovery.tpl new file mode 100644 index 000000000..48c505fa5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-discovery.tpl @@ -0,0 +1,30 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.clusterRoleBindingDiscovery" }} +--- +apiVersion: "rbac.authorization.k8s.io/v1" +{{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +kind: "RoleBinding" +{{- else }} +kind: "ClusterRoleBinding" +{{- end }} +metadata: + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + name: "weblogic-operator-rolebinding-discovery" + namespace: {{ .Release.Namespace | quote }} + {{- else }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrolebinding-discovery" | join "-" | quote }} + {{- end }} +roleRef: + apiGroup: "rbac.authorization.k8s.io" + kind: "ClusterRole" + name: "system:discovery" +subjects: +- kind: "ServiceAccount" + apiGroup: "" + name: {{ .serviceAccount | quote }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-general.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-general.tpl new file mode 100644 index 000000000..f2994da33 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-general.tpl @@ -0,0 +1,35 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.clusterRoleBindingGeneral" }} +--- +apiVersion: "rbac.authorization.k8s.io/v1" +{{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +kind: "RoleBinding" +{{- else }} +kind: "ClusterRoleBinding" +{{- end }} +metadata: + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + name: "weblogic-operator-rolebinding-general" + namespace: {{ .Release.Namespace | quote }} + {{- else }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrolebinding-general" | join "-" | quote }} + {{- end }} +roleRef: + apiGroup: "rbac.authorization.k8s.io" + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + kind: "Role" + name: "weblogic-operator-role-general" + {{- else }} + kind: "ClusterRole" + name: {{ list .Release.Namespace "weblogic-operator-clusterrole-general" | join "-" | quote }} + {{- end }} +subjects: +- kind: "ServiceAccount" + apiGroup: "" + name: {{ .serviceAccount | quote }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-nonresource.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-nonresource.tpl new file mode 100644 index 000000000..d998ab0e9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-clusterrolebinding-nonresource.tpl @@ -0,0 +1,21 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.clusterRoleBindingNonResource" }} +--- +apiVersion: "rbac.authorization.k8s.io/v1" +kind: "ClusterRoleBinding" +metadata: + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrolebinding-nonresource" | join "-" | quote }} +roleRef: + apiGroup: "rbac.authorization.k8s.io" + kind: "ClusterRole" + name: {{ list .Release.Namespace "weblogic-operator-clusterrole-nonresource" | join "-" | quote }} +subjects: +- kind: "ServiceAccount" + apiGroup: "" + name: {{ .serviceAccount | quote }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-cm.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-cm.tpl new file mode 100644 index 000000000..dd6594de2 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-cm.tpl @@ -0,0 +1,58 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorConfigMap" }} +--- +apiVersion: "v1" +data: + {{- if .externalRestEnabled }} + {{- if (hasKey . "externalRestIdentitySecret") }} + externalRestIdentitySecret: {{ .externalRestIdentitySecret | quote }} + {{- else }} + externalOperatorCert: {{ .externalOperatorCert | quote }} + {{- end }} + {{- end }} + {{- $configmap := (lookup "v1" "ConfigMap" .Release.Namespace "weblogic-operator-cm") }} + {{- if (and $configmap $configmap.data) }} + {{- $internalOperatorCert := index $configmap.data "internalOperatorCert" }} + {{- if $internalOperatorCert }} + internalOperatorCert: {{ $internalOperatorCert }} + {{- end }} + {{- end }} + serviceaccount: {{ .serviceAccount | quote }} + domainNamespaceSelectionStrategy: {{ (default "List" .domainNamespaceSelectionStrategy) | quote }} + domainNamespaces: {{ .domainNamespaces | uniq | sortAlpha | join "," | quote }} + {{- if .dedicated }} + dedicated: {{ .dedicated | quote }} + {{- end }} + {{- if .domainNamespaceLabelSelector }} + domainNamespaceLabelSelector: {{ .domainNamespaceLabelSelector | quote }} + {{- end }} + {{- if .domainNamespaceRegExp }} + domainNamespaceRegExp: {{ .domainNamespaceRegExp | quote }} + {{- end }} + {{- if .dns1123Fields }} + dns1123Fields: {{ .dns1123Fields | quote }} + {{- end }} + {{- if .featureGates }} + featureGates: {{ .featureGates | quote }} + {{- end }} + {{- if .introspectorJobNameSuffix }} + introspectorJobNameSuffix: {{ .introspectorJobNameSuffix | quote }} + {{- end }} + {{- if .externalServiceNameSuffix }} + externalServiceNameSuffix: {{ .externalServiceNameSuffix | quote }} + {{- end }} + {{- if .clusterSizePaddingValidationEnabled }} + clusterSizePaddingValidationEnabled: {{ .clusterSizePaddingValidationEnabled | quote }} + {{- end }} + {{- if .tokenReviewAuthentication }} + tokenReviewAuthentication: {{ .tokenReviewAuthentication | quote }} + {{- end }} +kind: "ConfigMap" +metadata: + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} + name: "weblogic-operator-cm" + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-dep.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-dep.tpl new file mode 100644 index 000000000..3fadac7dc --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-dep.tpl @@ -0,0 +1,158 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorDeployment" }} +--- +apiVersion: "apps/v1" +kind: "Deployment" +metadata: + name: "weblogic-operator" + namespace: {{ .Release.Namespace | quote }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +spec: + strategy: + type: Recreate + selector: + matchLabels: + weblogic.operatorName: {{ .Release.Namespace | quote }} + replicas: 1 + template: + metadata: + {{- with .annotations }} + annotations: + {{- end }} + {{- range $key, $value := .annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} + app: "weblogic-operator" + {{- range $key, $value := .labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + serviceAccountName: {{ .serviceAccount | quote }} + {{- with .nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: "weblogic-operator" + image: {{ .image | quote }} + imagePullPolicy: {{ .imagePullPolicy | quote }} + command: ["bash"] + args: ["/operator/operator.sh"] + env: + - name: "OPERATOR_NAMESPACE" + valueFrom: + fieldRef: + fieldPath: "metadata.namespace" + - name: "OPERATOR_POD_NAME" + valueFrom: + fieldRef: + fieldPath: "metadata.name" + - name: "OPERATOR_POD_UID" + valueFrom: + fieldRef: + fieldPath: "metadata.uid" + - name: "OPERATOR_VERBOSE" + value: "false" + - name: "JAVA_LOGGING_LEVEL" + value: {{ .javaLoggingLevel | quote }} + - name: "JAVA_LOGGING_MAXSIZE" + value: {{ .javaLoggingFileSizeLimit | default 20000000 | quote }} + - name: "JAVA_LOGGING_COUNT" + value: {{ .javaLoggingFileCount | default 10 | quote }} + {{- if .remoteDebugNodePortEnabled }} + - name: "REMOTE_DEBUG_PORT" + value: {{ .internalDebugHttpPort | quote }} + - name: "DEBUG_SUSPEND" + {{- if .suspendOnDebugStartup }} + value: "y" + {{- else }} + value: "n" + {{- end }} + {{- end }} + {{- if .mockWLS }} + - name: "MOCK_WLS" + value: "true" + {{- end }} + resources: + requests: + cpu: {{ .cpuRequests | default "250m" }} + memory: {{ .memoryRequests | default "512Mi" }} + limits: + {{- if .cpuLimits}} + cpu: {{ .cpuLimits }} + {{- end }} + {{- if .memoryLimits}} + memory: {{ .memoryLimits }} + {{- end }} + volumeMounts: + - name: "weblogic-operator-cm-volume" + mountPath: "/operator/config" + - name: "weblogic-operator-debug-cm-volume" + mountPath: "/operator/debug-config" + - name: "weblogic-operator-secrets-volume" + mountPath: "/operator/secrets" + readOnly: true + {{- if .elkIntegrationEnabled }} + - mountPath: "/logs" + name: "log-dir" + readOnly: false + {{- end }} + {{- if not .remoteDebugNodePortEnabled }} + livenessProbe: + exec: + command: + - "bash" + - "/operator/livenessProbe.sh" + initialDelaySeconds: 20 + periodSeconds: 5 + readinessProbe: + exec: + command: + - "bash" + - "/operator/readinessProbe.sh" + initialDelaySeconds: 2 + periodSeconds: 10 + {{- end }} + {{- if .elkIntegrationEnabled }} + - name: "logstash" + image: {{ .logStashImage | quote }} + args: [ "-f", "/logs/logstash.conf" ] + volumeMounts: + - name: "log-dir" + mountPath: "/logs" + env: + - name: "ELASTICSEARCH_HOST" + value: {{ .elasticSearchHost | quote }} + - name: "ELASTICSEARCH_PORT" + value: {{ .elasticSearchPort | quote }} + {{- end }} + {{- if .imagePullSecrets }} + imagePullSecrets: + {{ .imagePullSecrets | toYaml }} + {{- end }} + volumes: + - name: "weblogic-operator-cm-volume" + configMap: + name: "weblogic-operator-cm" + - name: "weblogic-operator-debug-cm-volume" + configMap: + name: "weblogic-operator-debug-cm" + optional: true + - name: "weblogic-operator-secrets-volume" + secret: + secretName: "weblogic-operator-secrets" + {{- if .elkIntegrationEnabled }} + - name: "log-dir" + emptyDir: + medium: "Memory" + {{- end }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-external-svc.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-external-svc.tpl new file mode 100644 index 000000000..44bfc1191 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-external-svc.tpl @@ -0,0 +1,30 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorExternalService" }} +{{- if or .externalRestEnabled .remoteDebugNodePortEnabled }} +--- +apiVersion: "v1" +kind: "Service" +metadata: + name: "external-weblogic-operator-svc" + namespace: {{ .Release.Namespace | quote }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +spec: + type: "NodePort" + selector: + app: "weblogic-operator" + ports: + {{- if .externalRestEnabled }} + - name: "rest" + port: 8081 + nodePort: {{ .externalRestHttpsPort }} + {{- end }} + {{- if .remoteDebugNodePortEnabled }} + - name: "debug" + port: {{ .internalDebugHttpPort }} + nodePort: {{ .externalDebugHttpPort }} + {{- end }} +{{- end }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-internal-svc.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-internal-svc.tpl new file mode 100644 index 000000000..0108738de --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-internal-svc.tpl @@ -0,0 +1,20 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorInternalService" }} +--- +apiVersion: "v1" +kind: "Service" +metadata: + name: "internal-weblogic-operator-svc" + namespace: {{ .Release.Namespace | quote }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +spec: + type: "ClusterIP" + selector: + app: "weblogic-operator" + ports: + - port: 8082 + name: "rest" +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-role.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-role.tpl new file mode 100644 index 000000000..e0c386b98 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-role.tpl @@ -0,0 +1,17 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorRole" }} +--- +kind: "Role" +apiVersion: "rbac.authorization.k8s.io/v1" +metadata: + name: "weblogic-operator-role" + namespace: {{ .Release.Namespace | quote }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +rules: +- apiGroups: [""] + resources: ["events", "secrets", "configmaps"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-rolebinding-namespace.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-rolebinding-namespace.tpl new file mode 100644 index 000000000..d55ed3f47 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-rolebinding-namespace.tpl @@ -0,0 +1,35 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorRoleBindingNamespace" }} +--- +{{- if .enableClusterRoleBinding }} +kind: "ClusterRoleBinding" +{{- else }} +kind: "RoleBinding" +{{- end }} +apiVersion: "rbac.authorization.k8s.io/v1" +metadata: + {{- if .enableClusterRoleBinding }} + name: {{ list .Release.Namespace "weblogic-operator-clusterrolebinding-namespace" | join "-" | quote }} + {{- else }} + name: "weblogic-operator-rolebinding-namespace" + namespace: {{ .domainNamespace | quote }} + {{- end }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +subjects: +- kind: "ServiceAccount" + name: {{ .serviceAccount | quote }} + namespace: {{ .Release.Namespace | quote }} + apiGroup: "" +roleRef: + {{- if (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} + kind: "Role" + name: "weblogic-operator-role-namespace" + {{- else }} + kind: "ClusterRole" + name: {{ list .Release.Namespace "weblogic-operator-clusterrole-namespace" | join "-" | quote }} + {{- end }} + apiGroup: "rbac.authorization.k8s.io" +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-rolebinding.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-rolebinding.tpl new file mode 100644 index 000000000..98a09424e --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-rolebinding.tpl @@ -0,0 +1,22 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorRoleBinding" }} +--- +kind: "RoleBinding" +apiVersion: "rbac.authorization.k8s.io/v1" +metadata: + name: "weblogic-operator-rolebinding" + namespace: {{ .Release.Namespace | quote }} + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} +subjects: +- kind: "ServiceAccount" + name: {{ .serviceAccount | quote }} + namespace: {{ .Release.Namespace | quote }} + apiGroup: "" +roleRef: + kind: "Role" + name: "weblogic-operator-role" + apiGroup: "rbac.authorization.k8s.io" +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-secret.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-secret.tpl new file mode 100644 index 000000000..6a7442718 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator-secret.tpl @@ -0,0 +1,25 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operatorSecrets" }} +--- +apiVersion: "v1" +kind: "Secret" +data: + {{- if (and .externalRestEnabled (hasKey . "externalOperatorKey")) }} + externalOperatorKey: {{ .externalOperatorKey | quote }} + {{- end }} + {{- $secret := (lookup "v1" "Secret" .Release.Namespace "weblogic-operator-secrets") }} + {{- if (and $secret $secret.data) }} + {{- $internalOperatorKey := index $secret.data "internalOperatorKey" }} + {{- if $internalOperatorKey }} + internalOperatorKey: {{ $internalOperatorKey }} + {{- end }} + {{- end }} +metadata: + labels: + weblogic.operatorName: {{ .Release.Namespace | quote }} + name: "weblogic-operator-secrets" + namespace: {{ .Release.Namespace | quote }} +type: "Opaque" +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator.tpl new file mode 100644 index 000000000..c24d7eebf --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_operator.tpl @@ -0,0 +1,30 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.operator" -}} +{{- include "operator.operatorClusterRoleGeneral" . }} +{{- include "operator.operatorClusterRoleNamespace" . }} +{{- if not (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +{{- include "operator.operatorClusterRoleNonResource" . }} +{{- end }} +{{- include "operator.operatorClusterRoleOperatorAdmin" . }} +{{- include "operator.operatorClusterRoleDomainAdmin" . }} +{{- include "operator.clusterRoleBindingGeneral" . }} +{{- include "operator.clusterRoleBindingAuthDelegator" . }} +{{- include "operator.clusterRoleBindingDiscovery" . }} +{{- if not (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +{{- include "operator.clusterRoleBindingNonResource" . }} +{{- end }} +{{- include "operator.operatorRole" . }} +{{- include "operator.operatorRoleBinding" . }} +{{- include "operator.operatorConfigMap" . }} +{{- include "operator.operatorSecrets" . }} +{{- include "operator.operatorDeployment" . }} +{{- include "operator.operatorInternalService" . }} +{{- include "operator.operatorExternalService" . }} +{{- if .enableClusterRoleBinding }} +{{- include "operator.operatorRoleBindingNamespace" . }} +{{- else }} +{{- include "operator.domainNamespaces" . }} +{{- end }} +{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_utils.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_utils.tpl new file mode 100644 index 000000000..9f2ed825c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_utils.tpl @@ -0,0 +1,493 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{/* +Start validation +*/}} +{{- define "utils.startValidation" -}} +{{- $scope := . -}} +{{- $context := dict "scope" $scope "path" list -}} +{{- $stack := list $context -}} +{{- $ignore := set $scope "validationContextStack" $stack -}} +{{- $ignore := include "utils.setCurrentValidationContext" $scope -}} +{{- end -}} + +{{/* +End validation +If there were any validation errors, report them and kill the helm chart installation. +*/}} +{{- define "utils.endValidation" -}} +{{- $scope := . -}} +{{- if hasKey $scope "validationErrors" -}} +{{- fail $scope.validationErrors -}} +{{- end -}} +{{- end -}} + +{{/* +Push a new validation context +*/}} +{{- define "utils.pushValidationContext" -}} +{{- $scope := index . 0 }} +{{- $scopeName := index . 1 }} +{{- $newScope := index $scope.validationScope $scopeName -}} +{{- $newPath := append $scope.validationPath $scopeName -}} +{{- $newContext := dict "scope" $newScope "path" $newPath -}} +{{- $newStack := append $scope.validationContextStack $newContext -}} +{{- $ignore := set $scope "validationContextStack" $newStack -}} +{{- $ignore := include "utils.setCurrentValidationContext" $scope -}} +{{- end -}} + +{{/* +Pop the validation context +*/}} +{{- define "utils.popValidationContext" -}} +{{- $scope := . }} +{{- $stack := $scope.validationContextStack -}} +{{- $ignore := set $scope "validationContextStack" (initial $stack) -}} +{{- $ignore := include "utils.setCurrentValidationContext" $scope -}} +{{- end -}} + +{{/* +Set the current validation context from the stack +*/}} +{{- define "utils.setCurrentValidationContext" -}} +{{- $scope := . }} +{{- $context := $scope.validationContextStack | last -}} +{{- $ignore := set $scope "validationScope" (index $context "scope") -}} +{{- $ignore := set $scope "validationPath" (index $context "path") -}} +{{- end -}} + +{{/* +Record a validation error (it will get reported later by utils.reportValidationErrors) +*/}} +{{- define "utils.recordValidationError" -}} +{{- $scope := index . 0 -}} +{{- $errorMsg := index . 1 -}} +{{- $path := $scope.validationPath -}} +{{- $pathStr := $path | join "." | trim -}} +{{- $scopedErrorMsg := (list "\n" $pathStr $errorMsg) | compact | join " " -}} +{{- if hasKey $scope "validationErrors" -}} +{{- $newValidationErrors := cat $scope.validationErrors $scopedErrorMsg -}} +{{- $ignore := set $scope "validationErrors" $newValidationErrors -}} +{{- else -}} +{{- $newValidationErrors := $scopedErrorMsg -}} +{{- $ignore := set $scope "validationErrors" $newValidationErrors -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether any errors have been reported +*/}} +{{- define "utils.haveValidationErrors" -}} +{{- if hasKey . "validationErrors" -}} + true +{{- end -}} +{{- end -}} + +{{/* +Determine whether a dictionary has a non-null value for a key +*/}} +{{- define "utils.dictionaryHasNonNullValue" -}} +{{- $dict := index . 0 -}} +{{- $name := index . 1 -}} +{{- if and (hasKey $dict $name) (not ( eq (typeOf (index $dict $name)) "" )) -}} + true +{{- end -}} +{{- end -}} + +{{/* +Verify that a value of a specific kind has been specified. +*/}} +{{- define "utils.verifyValue" -}} +{{- $requiredKind := index . 0 -}} +{{- $scope := index . 1 -}} +{{- $name := index . 2 -}} +{{- $isRequired := index . 3 -}} +{{- if $scope.trace -}} +{{- $errorMsg := cat "TRACE" $name $requiredKind $isRequired -}} +{{- $ignore := include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- end -}} +{{- $parent := $scope.validationScope -}} +{{- if include "utils.dictionaryHasNonNullValue" (list $parent $name) -}} +{{- $value := index $parent $name -}} +{{- $actualKind := kindOf $value -}} +{{- if eq $requiredKind $actualKind -}} + true +{{- else -}} +{{- $errorMsg := cat $name "must be a" $requiredKind ":" $actualKind -}} +{{- include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- end -}} +{{- else -}} +{{- if $isRequired -}} +{{- $errorMsg := cat $requiredKind $name "must be specified" -}} +{{- include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- else -}} + true +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Verify that a list value has been specified +*/}} +{{- define "utils.verifyListValue" -}} +{{- $requiredKind := index . 0 -}} +{{- $scope := index . 1 -}} +{{- $name := index . 2 -}} +{{- $isRequired := index . 3 -}} +{{- $parent := $scope.validationScope -}} +{{- $args := . -}} +{{- if include "utils.verifyValue" (list "slice" $scope $name $isRequired) -}} +{{- $status := dict -}} +{{- if hasKey $parent $name -}} +{{- $list := index $parent $name -}} +{{- range $value := $list -}} +{{- $actualKind := kindOf $value -}} +{{- if not (eq $requiredKind $actualKind) -}} +{{- $errorMsg := cat $name "must only contain" $requiredKind "elements:" $actualKind -}} +{{- include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- $ignore := set $status "error" true -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- if not (hasKey $status "error") -}} + true +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Verify a string value +*/}} +{{- define "utils.baseVerifyString" -}} +{{- include "utils.verifyValue" (prepend . "string") -}} +{{- end -}} + +{{/* +Verify a required string value +*/}} +{{- define "utils.verifyString" -}} +{{- include "utils.baseVerifyString" (append . true) -}} +{{- end -}} + +{{/* +Verify an optional string value +*/}} +{{- define "utils.verifyOptionalString" -}} +{{- include "utils.baseVerifyString" (append . false) -}} +{{- end -}} + +{{/* +Verify a boolean value +*/}} +{{- define "utils.baseVerifyBoolean" -}} +{{- include "utils.verifyValue" (prepend . "bool") -}} +{{- end -}} + +{{/* +Verify a required boolean value +*/}} +{{- define "utils.verifyBoolean" -}} +{{- include "utils.baseVerifyBoolean" (append . true) -}} +{{- end -}} + +{{/* +Verify an optional boolean value +*/}} +{{- define "utils.verifyOptionalBoolean" -}} +{{- include "utils.baseVerifyBoolean" (append . false) -}} +{{- end -}} + +{{/* +Verify an integer value +*/}} +{{- define "utils.baseVerifyInteger" -}} +{{- include "utils.verifyValue" (prepend . "float64") -}} +{{- end -}} + +{{/* +Verify a required integer value +*/}} +{{- define "utils.verifyInteger" -}} +{{- include "utils.baseVerifyInteger" (append . true) -}} +{{- end -}} + +{{/* +Verify an optional required integer value +*/}} +{{- define "utils.verifyOptionalInteger" -}} +{{- include "utils.baseVerifyInteger" (append . false) -}} +{{- end -}} + +{{/* +Verify a dictionary value +*/}} +{{- define "utils.baseVerifyDictionary" -}} +{{- include "utils.verifyValue" (prepend . "map") -}} +{{- end -}} + +{{/* +Verify a required dictionary value +*/}} +{{- define "utils.verifyDictionary" -}} +{{- include "utils.baseVerifyDictionary" (append . true) -}} +{{- end -}} + +{{/* +Verify an optional dictionary value +*/}} +{{- define "utils.verifyOptionalDictionary" -}} +{{- include "utils.baseVerifyDictionary" (append . false) -}} +{{- end -}} + +{{/* +Verify a enum string value +*/}} +{{- define "utils.baseVerifyEnum" -}} +{{- $scope := index . 0 -}} +{{- $name := index . 1 -}} +{{- $legalValues := index . 2 -}} +{{- $isRequired := index . 3 -}} +{{- if include "utils.baseVerifyString" (list $scope $name $isRequired) -}} +{{- $parent := $scope.validationScope -}} +{{- if include "utils.dictionaryHasNonNullValue" (list $parent $name) -}} +{{- $value := index $parent $name -}} +{{- if has $value $legalValues -}} + true +{{- else -}} +{{ $errorMsg := cat $name "must be one of the following values" $legalValues ":" $value -}} +{{- include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Verify a required enum string value +*/}} +{{- define "utils.verifyEnum" -}} +{{- include "utils.baseVerifyEnum" (append . true) -}} +{{- end -}} + +{{/* +Verify an optional enum string value +*/}} +{{- define "utils.verifyOptionalEnum" -}} +{{- include "utils.baseVerifyEnum" (append . false) -}} +{{- end -}} + +{{/* +Verify a kubernetes resource name string value +*/}} +{{- define "utils.baseVerifyResourceName" -}} +{{/* https://kubernetes.io/docs/concepts/overview/working-with-objects/names */}} +{{/* names: only lower case, numbers, dot, dash, max 253 */}} +{{/* https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set */}} +{{/* labels/selectors - upper & lower case, numbers, dot, dash, underscore, max 63 */}} +{{- $scope := index . 0 -}} +{{- $name := index . 1 -}} +{{- $max := index . 2 -}} +{{- $isRequired := index . 3 -}} +{{- if include "utils.baseVerifyString" (list $scope $name $isRequired) -}} +{{- $parent := $scope.validationScope -}} +{{- if include "utils.dictionaryHasNonNullValue" (list $parent $name) -}} +{{- $value := index $parent $name -}} +{{- $len := len $value -}} +{{- if and (le $len $max) (regexMatch "^[a-z0-9.-]+$" $value) -}} + true +{{- else -}} +{{- $errorMsg := cat $name "must only contain lower case letters, numbers, dashes and dots, and must not contain more than" $max "characters: " $value -}} +{{- include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- end -}} +{{- end -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Verify a required kubernetes resource name string value +*/}} +{{- define "utils.verifyResourceName" -}} +{{- include "utils.baseVerifyResourceName" (append . true) -}} +{{- end -}} + +{{/* +Verify an optional kubernetes resource name string value +*/}} +{{- define "utils.verifyOptionalResourceName" -}} +{{- include "utils.baseVerifyResourceName" (append . false) -}} +{{- end -}} + +{{/* +Verify external service name suffix string value +*/}} +{{- define "utils.verifyExternalServiceNameSuffix" -}} +{{- include "utils.baseVerifyResourceName" (append . false) -}} +{{- end -}} + +{{/* +Verify introspector job name suffix string value +*/}} +{{- define "utils.verifyIntrospectorJobNameSuffix" -}} +{{- include "utils.baseVerifyResourceName" (append . false) -}} +{{- end -}} + +{{/* +Verify a list of strings value +*/}} +{{- define "utils.baseVerifyStringList" -}} +{{- include "utils.verifyListValue" (prepend . "string") -}} +{{- end -}} + +{{/* +Verify a required list of strings value +*/}} +{{- define "utils.verifyStringList" -}} +{{- include "utils.baseVerifyStringList" (append . true) -}} +{{- end -}} + +{{/* +Verify an optional list of strings value +*/}} +{{- define "utils.verifyOptionalStringList" -}} +{{- include "utils.baseVerifyStringList" (append . false) -}} +{{- end -}} + +{{/* +Verify a list of dictionaries value +*/}} +{{- define "utils.baseVerifyDictionaryList" -}} +{{- include "utils.verifyListValue" (prepend . "map") -}} +{{- end -}} + +{{/* +Verify a required list of dictionaries value +*/}} +{{- define "utils.verifyDictionaryList" -}} +{{- include "utils.baseVerifyDictionaryList" (append . true) -}} +{{- end -}} + +{{/* +Verify an optional list of dictionaries value +*/}} +{{- define "utils.verifyOptionalDictionaryList" -}} +{{- include "utils.baseVerifyDictionaryList" (append . false) -}} +{{- end -}} + +{{/* +Merge a set of dictionaries into a single dictionary. + +The scope must be a list of dictionaries, starting with the least specific +and ending with the most specific. + +First it makes an empty destinaction dictionary, then iterates over the dictionaries, +overlaying their values on the destination dictionary. + +If a value is null, then it removes that key from the destination dictionary. + +If the value is already present in the destination dictionary, and the old and +new values are both dictionaries, it merges them into the destination. +*/}} +{{- define "utils.mergeDictionaries" -}} +{{- $dest := dict -}} +{{- range $src := . -}} +{{- if not (empty $src) -}} +{{- range $key, $value := $src -}} +{{- $ignore := include "utils.mergeDictionaryValue" (list $dest $key $value) -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- toYaml $dest -}} +{{- end -}} + +{{/* +Merge a value into a dictionary. +This is like helm's 'merge' function, except that it handles null entries too. +*/}} +{{- define "utils.mergeDictionaryValue" -}} +{{- $dest := index . 0 -}} +{{- $key := index . 1 -}} +{{- $newValue := index . 2 -}} +{{- $newType := typeOf $newValue -}} +{{- if hasKey $dest $key -}} +{{- if eq $newType "" -}} +{{/* # if the value already existed, and the new value is null, remove the old value */}} +{{- $ignore := unset $dest $key -}} +{{- else -}} +{{- $oldValue := index $dest $key -}} +{{- $oldKind := kindOf $oldValue -}} +{{- $newKind := kindOf $newValue -}} +{{- if (and (eq $oldKind "map") (eq $newKind "map")) -}} +{{/* # if both values are maps, merge them */}} +{{- $merged := include "utils.mergeDictionaries" (list $oldValue $newValue) | fromYaml -}} +{{- $ignore := set $dest $key $merged -}} +{{- else -}} +{{/* # replace the old value with the new one */}} +{{- $ignore := set $dest $key $newValue -}} +{{- end -}} +{{- end -}} +{{- else -}} +{{- if not (eq $newType "") -}} +{{/* #if there was no old value, and the new value isn't null, use the new value */}} +{{- $ignore := set $dest $key $newValue -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Make a writable copy of a dictionary. +TBD - does helm provide a clone method we can use instead? +*/}} +{{- define "utils.cloneDictionary" -}} +{{- include "utils.mergeDictionaries" (list .) -}} +{{- end -}} + +{{/* +Verify that a list of values (exclude) can not be defined if another value (key) is already defined +*/}} +{{- define "utils.mutexValue" -}} +{{- $scope := index . 0 -}} +{{- $key := index . 1 -}} +{{- $exclude := index . 2 -}} +{{- $type := index . 3 -}} +{{- $parent := $scope.validationScope -}} +{{- $args := . -}} +{{- $status := dict -}} +{{- if hasKey $parent $key -}} +{{- range $value := $exclude -}} +{{- if hasKey $parent $value -}} +{{- $errorMsg := cat $value "can not be present when" $key "is defined" " " -}} +{{- include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- $ignore := set $status "error" true -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- if not (hasKey $status "error") -}} + true +{{- end -}} +{{- end -}} + +{{/* +Verify that a list of strings can not be defined if another string is already defined +*/}} +{{- define "utils.mutexString" -}} +{{- include "utils.mutexValue" (append . "string") -}} +{{- end -}} + +{{/* +Verify that a Kubernetes resource exists in a given namespace +*/}} +{{- define "utils.verifyK8SResource" -}} +{{- $scope := index . 0 -}} +{{- $name := index . 1 -}} +{{- $type := index . 2 -}} +{{- $namespace := index . 3 -}} +{{- $foundNS := (lookup "v1" "Namespace" "" $namespace) }} +{{- if $foundNS }} +{{- $foundResource := (lookup "v1" $type $namespace $name) }} +{{- if not $foundResource }} +{{- $errorMsg := cat $type $name " not found in namespace " $namespace -}} +{{- include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_validate-inputs.tpl b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_validate-inputs.tpl new file mode 100644 index 000000000..a6ee7dd02 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/_validate-inputs.tpl @@ -0,0 +1,63 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- define "operator.validateInputs" -}} +{{- $scope := include "utils.cloneDictionary" . | fromYaml -}} +{{- $ignore:= include "utils.startValidation" $scope -}} +{{- $ignore := include "utils.pushValidationContext" (list $scope "Release") -}} +{{- $ignore := include "utils.verifyResourceName" (list $scope "Namespace" 63) -}} +{{- $ignore := include "utils.popValidationContext" $scope -}} +{{- $ignore := include "utils.verifyString" (list $scope "serviceAccount") -}} +{{- $ignore := include "utils.verifyK8SResource" (list $scope .serviceAccount "ServiceAccount" .Release.Namespace) -}} +{{- $ignore := include "utils.verifyString" (list $scope "image") -}} +{{- $ignore := include "utils.verifyEnum" (list $scope "imagePullPolicy" (list "Always" "IfNotPresent" "Never")) -}} +{{- $ignore := include "utils.verifyOptionalDictionaryList" (list $scope "imagePullSecrets") -}} +{{- $ignore := include "utils.verifyEnum" (list $scope "javaLoggingLevel" (list "SEVERE" "WARNING" "INFO" "CONFIG" "FINE" "FINER" "FINEST")) -}} +{{- if include "utils.verifyBoolean" (list $scope "externalRestEnabled") -}} +{{- if $scope.externalRestEnabled -}} +{{- $ignore := include "utils.verifyInteger" (list $scope "externalRestHttpsPort") -}} +{{- $ignore := include "utils.mutexString" (list $scope "externalRestIdentitySecret" (list "externalOperatorKey" "externalOperatorCert")) -}} +{{- if (or (hasKey $scope "externalOperatorCert") (hasKey $scope "externalOperatorKey")) -}} +{{- $ignore := include "utils.verifyString" (list $scope "externalOperatorCert") -}} +{{- $ignore := include "utils.verifyString" (list $scope "externalOperatorKey") -}} +{{- else }} +{{- $ignore := include "utils.verifyString" (list $scope "externalRestIdentitySecret") -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- if include "utils.verifyBoolean" (list $scope "remoteDebugNodePortEnabled") -}} +{{- if $scope.remoteDebugNodePortEnabled -}} +{{- $ignore := include "utils.verifyBoolean" (list $scope "suspendOnDebugStartup") -}} +{{- $ignore := include "utils.verifyInteger" (list $scope "internalDebugHttpPort") -}} +{{- $ignore := include "utils.verifyInteger" (list $scope "externalDebugHttpPort") -}} +{{- end -}} +{{- end -}} +{{- $ignore := include "utils.verifyOptionalBoolean" (list $scope "enableClusterRoleBinding") -}} +{{- if and .enableClusterRoleBinding (or (eq (default "List" .domainNamespaceSelectionStrategy) "Dedicated") (and .dedicated (eq (default "List" .domainNamespaceSelectionStrategy) "List"))) }} +{{- $errorMsg := "The enableClusterRoleBinding value may not be true when either dedicated is true or domainNamespaceSelectionStrategy is Dedicated" -}} +{{- include "utils.recordValidationError" (list $scope $errorMsg) -}} +{{- end -}} +{{- if eq (default "List" $scope.domainNamespaceSelectionStrategy) "List" -}} +{{- $ignore := include "utils.verifyStringList" (list $scope "domainNamespaces") -}} +{{- end -}} +{{- if include "utils.verifyBoolean" (list $scope "elkIntegrationEnabled") -}} +{{- if $scope.elkIntegrationEnabled -}} +{{- $ignore := include "utils.verifyString" (list $scope "logStashImage") -}} +{{- $ignore := include "utils.verifyString" (list $scope "elasticSearchHost") -}} +{{- $ignore := include "utils.verifyInteger" (list $scope "elasticSearchPort") -}} +{{- end -}} +{{- end -}} +{{- $ignore := include "utils.verifyOptionalBoolean" (list $scope "dedicated") -}} +{{- $ignore := include "utils.verifyOptionalEnum" (list $scope "domainNamespaceSelectionStrategy" (list "List" "LabelSelector" "RegExp" "Dedicated")) -}} +{{- if eq (default "List" $scope.domainNamespaceSelectionStrategy) "LabelSelector" -}} +{{- $ignore := include "utils.verifyString" (list $scope "domainNamespaceLabelSelector") -}} +{{- end -}} +{{- if eq (default "List" $scope.domainNamespaceSelectionStrategy) "RegExp" -}} +{{- $ignore := include "utils.verifyString" (list $scope "domainNamespaceRegExp") -}} +{{- end -}} +{{- $ignore := include "utils.verifyOptionalBoolean" (list $scope "mockWLS") -}} +{{- $ignore := include "utils.verifyIntrospectorJobNameSuffix" (list $scope "introspectorJobNameSuffix" 25) -}} +{{- $ignore := include "utils.verifyExternalServiceNameSuffix" (list $scope "externalServiceNameSuffix" 10) -}} +{{- $ignore := include "utils.verifyOptionalBoolean" (list $scope "clusterSizePaddingValidationEnabled") -}} +{{- $ignore := include "utils.endValidation" $scope -}} +{{- end -}} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/main.yaml b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/main.yaml new file mode 100644 index 000000000..fb7e731f9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/templates/main.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +{{- $scope := include "utils.cloneDictionary" .Values | fromYaml -}} +{{- $ignore := set $scope "Files" .Files -}} +{{- $ignore := set $scope "Chart" .Chart -}} +{{- $ignore := set $scope "Release" .Release -}} +{{- $ignore := set $scope "APIVersions" .Capabilities.APIVersions -}} + +{{ include "operator.validateInputs" $scope }} +{{- include "operator.operator" $scope }} diff --git a/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/values.yaml b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/values.yaml new file mode 100644 index 000000000..dac9a5382 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/charts/weblogic-operator/values.yaml @@ -0,0 +1,224 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# serviceAccount specifies the name of the ServiceAccount in the operator's namespace that the +# operator will use to make requests to the Kubernetes API server. +# The customer is responsible for creating the ServiceAccount in the same namespace as this Helm release. +# If not specified, the the operator will use the Helm release namespace's 'default' ServiceAccount. +serviceAccount: "default" + +# domainNamespaceSelectionStrategy specifies how the operator will select the set of namespaces +# that it will manage. Legal values are: List, LabelSelector, RegExp, and Dedicated. If set to 'List', +# then the operator will manage the set of namespaces listed by the 'domainNamespaces' value. +# If set to 'LabelSelector', then the operator will manage the set of namespaces discovered by a list +# of namespaces using the value specified by 'domainNamespaceLabelSelector' as a label selector. +# If set to 'RegExp', then the operator will manage the set of namespaces discovered by a list +# of namespaces using the value specified by 'domainNamespaceRegExp' as a regular expression matched +# against the namespace names. +# If set to 'Dedicated', then operator will manage WebLogic Domains only in the same namespace +# where the operator itself is deployed, which is the namespace of the Helm release. +domainNamespaceSelectionStrategy: List + +# This value is deprecated. Please use 'domainNamespaceSelectionStrategy: Dedicated'. +# dedicated specifies if this operator will manage WebLogic Domains only in the same namespace in +# which the operator itself is deployed. If set to 'true', then the 'domainNamespaces' value below +# is ignored. This value is ignored if 'domainNamespaceSelectionStrategy' is set to a value other +# than 'List'. +# dedicated: false + +# domainNamespaces specifies list of WebLogic Domain namespaces that this operator manages. This value +# is ignored if 'domainNamespaceSelectionStrategy' is not 'List'. The customer is responsible for creating these +# namespaces. If not specified, then the operator will manage WebLogic Domains in the Kubernetes 'default' namespace. +# +# Example: In the configuration below, the operator will manage namespace1 and namespace2. +# +# domainNamespaces: +# - "namespace1" +# - "namespace2" +domainNamespaces: +- "default" + +# domainNamespaceLabelSelector specifies the label selector value that the operator will use when listing +# namespaces in search of the namespaces that contain WebLogic Domains that this operator will manage. Ignored +# if 'domainNamespaceSelectionStrategy' is not 'LabelSelector'. +# +# Example: manage any namespace with a label named "weblogic-operator". +# +# domainNamespaceLabelSelector: "weblogic-operator" +# +# domainNamespaceLabelSelector: + +# domainNamespaceRegExp specifies a regular expression that will be matched against namespace names when listing +# namespaces in search of the namespaces that contain WebLogic Domains that this operator will manage. Ignored +# if 'domainNamespaceSelectionStrategy' is not 'RegExp'. +# +# Example: manage any namespace where the namespace name starts with "prod". +# +# domainNamespaceRegExp: "^prod" +# +# domainNamespaceRegExp: + +# enableClusterRoleBinding specifies whether the roles necessary for the operator to manage domains +# will be granted using a ClusterRoleBinding rather than using RoleBindings in each managed namespace. +enableClusterRoleBinding: false + +# image specifies the container image containing the operator. +image: "ghcr.io/oracle/weblogic-kubernetes-operator:3.3.0" + +# imagePullPolicy specifies the image pull policy for the operator's container image. +imagePullPolicy: IfNotPresent + +# imagePullSecrets contains an optional list of Kubernetes Secrets, in the operator's namespace, +# that are needed to access the registry containing the operator's container image. +# The customer is responsible for creating the Secret. +# If no Secrets are required, then omit this property. +# +# Example: a Secret is needed, and has been stored in 'my-operator-secret' +# +# imagePullSecrets: +# - name: "my-operator-secret" + +# externalRestEnabled specifies whether the the operator's REST interface is exposed +# outside of the Kubernetes cluster on the port specified by the 'externalRestHttpsPort' +# property. +# +# If set to true, then the customer must provide the SSL certificate and private key for +# the operator's external REST interface by specifying the 'externalOperatorCert' and +# 'externalOperatorKey' properties. +externalRestEnabled: false + +# externalRestHttpsPort specifies the node port that should be allocated for the external operator REST HTTPS interface. +# This parameter is required if 'externalRestEnabled' is true. +# Otherwise, it is ignored. +externalRestHttpsPort: 31001 + +# The name of the Secret used to store the certificate and private key to use for the external operator REST HTTPS interface. +# The Secret has to be created in the same namespace of the WebLogic operator. +# This parameter is required if 'externalRestEnabled' is true. Otherwise, it is ignored. +# As example, an external REST identity can be created using the following sample script +# kubernetes/samples/scripts/rest/generate-external-rest-identity.sh +# externalRestIdentitySecret: + +# elkIntegrationEnabled specifies whether or not ELK integration is enabled. +elkIntegrationEnabled: false + +# logStashImage specifies the container image containing logstash. +# This parameter is ignored if 'elkIntegrationEnabled' is false. +logStashImage: "logstash:6.6.0" + +# elasticSearchHost specifies the hostname of where elasticsearch is running. +# This parameter is ignored if 'elkIntegrationEnabled' is false. +elasticSearchHost: "elasticsearch.default.svc.cluster.local" + +# elasticSearchPort specifies the port number of where elasticsearch is running. +# This parameter is ignored if 'elkIntegrationEnabled' is false. +elasticSearchPort: 9200 + +# featureGates specifies a set of key=value pairs separated by commas that describe whether a given +# operator feature is enabled. You enable a feature by including a key=value pair where the key is the +# feature name and the value is "true". This will allow the operator team to release features that +# are not yet ready to be enabled by default, but that are ready for testing by customers. Once a feature is +# stable then it will be enabled by default and can not be disabled using this configuration. +# featureGates: "...,AuxiliaryImage=true" + +# javaLoggingLevel specifies the Java logging level for the operator. This affects the operator pod's +# log output and the contents of log files in the container's /logs/ directory. +# Valid values are: "SEVERE", "WARNING", "INFO", "CONFIG", "FINE", "FINER", and "FINEST". +javaLoggingLevel: "INFO" + +# javaLoggingFileSizeLimit specifies the maximum size in bytes for an individual Java logging file in the operator container's +# /logs/ directory. +javaLoggingFileSizeLimit: 20000000 + +# javaLoggingFileCount specifies the number of Java logging files to preserve in the operator container's /logs/ +# directory as the files are rotated. +javaLoggingFileCount: 10 + +# labels specifies a set of key-value labels that will be added to each pod running the operator. +# See https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +#labels: + +# annotations specifies a set of key-value annotations that will be added to each pod running the operator. +# See https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +#annotations: + +# nodeSelector specifies a matching rule that the Kubernetes scheduler will use when selecting the node +# where the operator will run. If the nodeSelector value is specified, then this content will be added to +# the operator's deployment. See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector +# for more information on node selectors. +#nodeSelector: + +# affinity specifies a set of matching rules related to the presence of other workloads that the Kubernetes scheduler +# will use when selecting the node where the operator will run. If the affinity value is specified, then this content +# will be added to the operator's deployment. See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity +# for more information on affinity and anti-affinity. +#affinity: + +# Values related to debugging the operator. +# Customers should not need to use the following properties + +# remoteDebugNodePortEnabled specifies whether or not the operator will provide a Java remote debug interface on the +# provided port. If the 'suspendOnDebugStartup' property is specified, the operator will suspend execution +# until a remote debugger has attached. +# The 'internalDebugHttpPort' property controls the port number inside the Kubernetes +# cluster and the 'externalDebugHttpPort' property controls the port number outside +# the Kubernetes cluster. +remoteDebugNodePortEnabled: false + +#suspendOnDebugStartup specifies whether the operator will suspend on startup when a Java remote debugging is enabled. +suspendOnDebugStartup: false + +# internalDebugHttpPort specifies the port number inside the Kubernetes cluster for the operator's Java +# remote debug interface. +# This parameter is required if 'remoteDebugNodePortEnabled' is true. +# Otherwise, it is ignored. +internalDebugHttpPort: 30999 + +# externalDebugHttpPort specifies the node port that should be allocated for the operator's +# Java remote debug interface. +# This parameter is required if 'remoteDebugNodePortEnabled' is true. +# Otherwise, it is ignored. +externalDebugHttpPort: 30999 + +# dns1123Fields overrides the default list of field names that the operator +# converts to DNS-1123 legal values when replacing variable references in the +# Domain resource. The default list can be found inside the class LegalNames +# in the oracle.kubernetes.operator.helpers package. +# Supply a comma separated list of field names to customize the list of fields +# such as "name, claimName, volumeName", or leave it commented out to use +# the default list of field names. +# dns1123Fields: "" + +# introspectorJobNameSuffix overrides the default suffix that the operator uses +# to append to the domainUID to form the name of the domain introspector job name. +# Note that the resultant job name should not be more than 58 characters due to +# the Kubernetes limit to the name of a job and Kubernetes appends five additional +# characters to the name of the pod that is created by the job controller. +# The default suffix is '-introspector'. +# The default suffix in pre-3.1.0 is "-introspect-domain-job" +introspectorJobNameSuffix: "-introspector" + +# externalServiceNameSuffix overrides the default suffix that the operator uses +# to append to the domainUID and the WebLogic admin server name, to form the name +# of the domain's admin server external service. +# Note that the resultant name should not be more than 63 characters due to +# the Kubernetes limit to the name of a service. +# The default suffix is '-ext'. +# The default suffix in pre-3.1.0 is "-external". +externalServiceNameSuffix: "-ext" + +# clusterSizePaddingValidationEnabled specifies if additional one or two characters +# need to be reserved to account for longer managed server names because of an increased +# cluster size. +# The default value is true. +clusterSizePaddingValidationEnabled: true + +# tokenReviewAuthentication, if set to true, specifies whether the the operator's REST API should use +# 1. Kubernetes token review API for authenticating users, and +# 2. Kubernetes subject access review API for authorizing a user's operation (get, list, +# patch, etc) on a resource. +# 3. Update the Domain resource using the operator's privileges. +# This parameter, if set to false, will use the caller's bearer token for any update +# to the Domain resource so that it is done using the caller's privileges. +# The default value is false. +#tokenReviewAuthentication: false diff --git a/OracleWebCenterPortal/kubernetes/common/createFMWJRFDomain.py b/OracleWebCenterPortal/kubernetes/common/createFMWJRFDomain.py new file mode 100644 index 000000000..bde936ca5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/common/createFMWJRFDomain.py @@ -0,0 +1,332 @@ +# Copyright (c) 2014, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +import os +import sys + +import com.oracle.cie.domain.script.jython.WLSTException as WLSTException + +class Infra12213Provisioner: + + MACHINES = { + 'machine1' : { + 'NMType': 'SSL', + 'ListenAddress': 'localhost', + 'ListenPort': 5658 + } + } + + JRF_12213_TEMPLATES = { + 'baseTemplate' : '@@ORACLE_HOME@@/wlserver/common/templates/wls/wls.jar', + 'extensionTemplates' : [ + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.jrf_template.jar', + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.jrf.ws.async_template.jar', + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.wsmpm_template.jar', + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.ums_template.jar', + '@@ORACLE_HOME@@/em/common/templates/wls/oracle.em_wls_template.jar' + ], + 'serverGroupsToTarget' : [ 'JRF-MAN-SVR', 'WSMPM-MAN-SVR' ] + } + + def __init__(self, oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName): + self.oracleHome = self.validateDirectory(oracleHome) + self.javaHome = self.validateDirectory(javaHome) + self.domainParentDir = self.validateDirectory(domainParentDir, create=True) + return + + def createInfraDomain(self, domainName, user, password, db, dbPrefix, dbPassword, adminListenPort, adminName, + managedNameBase, managedServerPort, prodMode, managedCount, clusterName, + exposeAdminT3Channel=None, t3ChannelPublicAddress=None, t3ChannelPort=None): + domainHome = self.createBaseDomain(domainName, user, password, adminListenPort, adminName, managedNameBase, + managedServerPort, prodMode, managedCount, clusterName + ) + self.extendDomain(domainHome, db, dbPrefix, dbPassword, exposeAdminT3Channel, t3ChannelPublicAddress, + t3ChannelPort) + + def createBaseDomain(self, domainName, user, password, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName): + baseTemplate = self.replaceTokens(self.JRF_12213_TEMPLATES['baseTemplate']) + + readTemplate(baseTemplate) + setOption('DomainName', domainName) + setOption('JavaHome', self.javaHome) + if (prodMode == 'true'): + setOption('ServerStartMode', 'prod') + else: + setOption('ServerStartMode', 'dev') + set('Name', domainName) + + admin_port = int(adminListenPort) + ms_port = int(managedServerPort) + ms_count = int(managedCount) + + # Create Admin Server + # ======================= + print 'Creating Admin Server...' + cd('/Servers/AdminServer') + #set('ListenAddress', '%s-%s' % (domain_uid, admin_server_name_svc)) + set('ListenPort', admin_port) + set('Name', adminName) + + # Define the user password for weblogic + # ===================================== + cd('/Security/' + domainName + '/User/weblogic') + set('Name', user) + set('Password', password) + + # Create a cluster + # ====================== + print 'Creating cluster...' + cd('/') + cl=create(clusterName, 'Cluster') + + # Create managed servers + for index in range(0, ms_count): + cd('/') + msIndex = index+1 + cd('/') + name = '%s%s' % (managedNameBase, msIndex) + create(name, 'Server') + cd('/Servers/%s/' % name ) + print('managed server name is %s' % name); + set('ListenPort', ms_port) + set('NumOfRetriesBeforeMSIMode', 0) + set('RetryIntervalBeforeMSIMode', 1) + set('Cluster', clusterName) + + # Create Node Manager + # ======================= + print 'Creating Node Managers...' + for machine in self.MACHINES: + cd('/') + create(machine, 'Machine') + cd('Machine/' + machine) + create(machine, 'NodeManager') + cd('NodeManager/' + machine) + for param in self.MACHINES[machine]: + set(param, self.MACHINES[machine][param]) + + + setOption('OverwriteDomain', 'true') + domainHome = self.domainParentDir + '/' + domainName + print 'Will create Base domain at ' + domainHome + + print 'Writing base domain...' + writeDomain(domainHome) + closeTemplate() + print 'Base domain created at ' + domainHome + return domainHome + + + def extendDomain(self, domainHome, db, dbPrefix, dbPassword, exposeAdminT3Channel, t3ChannelPublicAddress, + t3ChannelPort): + print 'Extending domain at ' + domainHome + print 'Database ' + db + readDomain(domainHome) + setOption('AppDir', self.domainParentDir + '/applications') + + print 'ExposeAdminT3Channel %s with %s:%s ' % (exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) + if 'true' == exposeAdminT3Channel: + self.enable_admin_channel(t3ChannelPublicAddress, t3ChannelPort) + + print 'Applying JRF templates...' + for extensionTemplate in self.JRF_12213_TEMPLATES['extensionTemplates']: + addTemplate(self.replaceTokens(extensionTemplate)) + + print 'Extension Templates added' + + print 'Configuring the Service Table DataSource...' + fmwDb = 'jdbc:oracle:thin:@' + db + print 'fmwDatabase ' + fmwDb + cd('/JDBCSystemResource/LocalSvcTblDataSource/JdbcResource/LocalSvcTblDataSource') + cd('JDBCDriverParams/NO_NAME_0') + set('DriverName', 'oracle.jdbc.OracleDriver') + set('URL', fmwDb) + set('PasswordEncrypted', dbPassword) + + stbUser = dbPrefix + '_STB' + cd('Properties/NO_NAME_0/Property/user') + set('Value', stbUser) + + print 'Getting Database Defaults...' + getDatabaseDefaults() + + print 'Targeting Server Groups...' + managedName= '%s%s' % (managedNameBase, 1) + print "Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:" + managedName + serverGroupsToTarget = list(self.JRF_12213_TEMPLATES['serverGroupsToTarget']) + cd('/') + setServerGroups(managedName, serverGroupsToTarget) + print "Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:" + managedName + cd('/Servers/' + managedName) + set('CoherenceClusterSystemResource', 'defaultCoherenceCluster') + + print 'Targeting Cluster ...' + cd('/') + print "Set CoherenceClusterSystemResource to defaultCoherenceCluster for cluster:" + clusterName + cd('/Cluster/' + clusterName) + set('CoherenceClusterSystemResource', 'defaultCoherenceCluster') + print "Set WLS clusters as target of defaultCoherenceCluster:" + clusterName + cd('/CoherenceClusterSystemResource/defaultCoherenceCluster') + set('Target', clusterName) + + print 'Preparing to update domain...' + updateDomain() + print 'Domain updated successfully' + closeDomain() + return + + + ########################################################################### + # Helper Methods # + ########################################################################### + + def validateDirectory(self, dirName, create=False): + directory = os.path.realpath(dirName) + if not os.path.exists(directory): + if create: + os.makedirs(directory) + else: + message = 'Directory ' + directory + ' does not exist' + raise WLSTException(message) + elif not os.path.isdir(directory): + message = 'Directory ' + directory + ' is not a directory' + raise WLSTException(message) + return self.fixupPath(directory) + + + def fixupPath(self, path): + result = path + if path is not None: + result = path.replace('\\', '/') + return result + + + def replaceTokens(self, path): + result = path + if path is not None: + result = path.replace('@@ORACLE_HOME@@', oracleHome) + return result + + def enable_admin_channel(self, admin_channel_address, admin_channel_port): + if admin_channel_address == None or admin_channel_port == 'None': + return + cd('/') + admin_server_name = get('AdminServerName') + print('setting admin server t3channel for ' + admin_server_name) + cd('/Servers/' + admin_server_name) + create('T3Channel', 'NetworkAccessPoint') + cd('/Servers/' + admin_server_name + '/NetworkAccessPoint/T3Channel') + set('ListenPort', int(admin_channel_port)) + set('PublicPort', int(admin_channel_port)) + set('PublicAddress', admin_channel_address) + +############################# +# Entry point to the script # +############################# + +def usage(): + print sys.argv[0] + ' -oh -jh -parent -name ' + \ + '-user -password ' + \ + '-rcuDb -rcuPrefix -rcuSchemaPwd ' \ + '-adminListenPort -adminName ' \ + '-managedNameBase -managedServerPort -prodMode ' \ + '-managedServerCount -clusterName ' \ + '-exposeAdminT3Channel -t3ChannelPublicAddress

' \ + '-t3ChannelPort ' + sys.exit(0) + +# Uncomment for Debug only +#print str(sys.argv[0]) + " called with the following sys.argv array:" +#for index, arg in enumerate(sys.argv): +# print "sys.argv[" + str(index) + "] = " + str(sys.argv[index]) + +if len(sys.argv) < 16: + usage() + +#oracleHome will be passed by command line parameter -oh. +oracleHome = None +#javaHome will be passed by command line parameter -jh. +javaHome = None +#domainParentDir will be passed by command line parameter -parent. +domainParentDir = None +#domainUser is hard-coded to weblogic. You can change to other name of your choice. Command line paramter -user. +domainUser = 'weblogic' +#domainPassword will be passed by Command line parameter -password. +domainPassword = None +#rcuDb will be passed by command line parameter -rcuDb. +rcuDb = None +#change rcuSchemaPrefix to your infra schema prefix. Command line parameter -rcuPrefix. +rcuSchemaPrefix = 'DEV12' +#change rcuSchemaPassword to your infra schema password. Command line parameter -rcuSchemaPwd. +rcuSchemaPassword = None +exposeAdminT3Channel = None +t3ChannelPort = None +t3ChannelPublicAddress = None +i = 1 +while i < len(sys.argv): + if sys.argv[i] == '-oh': + oracleHome = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-jh': + javaHome = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-parent': + domainParentDir = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-name': + domainName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-user': + domainUser = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-password': + domainPassword = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuDb': + rcuDb = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuPrefix': + rcuSchemaPrefix = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuSchemaPwd': + rcuSchemaPassword = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-adminListenPort': + adminListenPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-adminName': + adminName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedNameBase': + managedNameBase = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedServerPort': + managedServerPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-prodMode': + prodMode = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedServerCount': + managedCount = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-clusterName': + clusterName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-t3ChannelPublicAddress': + t3ChannelPublicAddress = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-t3ChannelPort': + t3ChannelPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-exposeAdminT3Channel': + exposeAdminT3Channel = sys.argv[i + 1] + i += 2 + else: + print 'Unexpected argument switch at position ' + str(i) + ': ' + str(sys.argv[i]) + usage() + sys.exit(1) + +provisioner = Infra12213Provisioner(oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName) +provisioner.createInfraDomain(domainName, domainUser, domainPassword, rcuDb, rcuSchemaPrefix, rcuSchemaPassword, + adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, + clusterName, exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) \ No newline at end of file diff --git a/OracleWebCenterPortal/kubernetes/common/createFMWRestrictedJRFDomain.py b/OracleWebCenterPortal/kubernetes/common/createFMWRestrictedJRFDomain.py new file mode 100644 index 000000000..acfe5da80 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/common/createFMWRestrictedJRFDomain.py @@ -0,0 +1,291 @@ +# Copyright (c) 2014, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +import os +import sys + +import com.oracle.cie.domain.script.jython.WLSTException as WLSTException + +class Infra12213Provisioner: + + MACHINES = { + 'machine1' : { + 'NMType': 'SSL', + 'ListenAddress': 'localhost', + 'ListenPort': 5658 + } + } + + JRF_12213_TEMPLATES = { + 'baseTemplate' : '@@ORACLE_HOME@@/wlserver/common/templates/wls/wls.jar', + 'extensionTemplates' : [ + '@@ORACLE_HOME@@/oracle_common/common/templates/wls/oracle.jrf_restricted_template.jar', + '@@ORACLE_HOME@@/em/common/templates/wls/oracle.em_wls_restricted_template.jar' + ], + 'serverGroupsToTarget' : [ 'JRF-MAN-SVR', 'WSMPM-MAN-SVR' ] + } + + def __init__(self, oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName): + self.oracleHome = self.validateDirectory(oracleHome) + self.javaHome = self.validateDirectory(javaHome) + self.domainParentDir = self.validateDirectory(domainParentDir, create=True) + return + + def createInfraDomain(self, domainName, user, password, adminListenPort, adminName, + managedNameBase, managedServerPort, prodMode, managedCount, clusterName, + exposeAdminT3Channel=None, t3ChannelPublicAddress=None, t3ChannelPort=None): + domainHome = self.createBaseDomain(domainName, user, password, adminListenPort, adminName, managedNameBase, + managedServerPort, prodMode, managedCount, clusterName + ) + self.extendDomain(domainHome, exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) + + def createBaseDomain(self, domainName, user, password, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName): + baseTemplate = self.replaceTokens(self.JRF_12213_TEMPLATES['baseTemplate']) + + readTemplate(baseTemplate) + setOption('DomainName', domainName) + setOption('JavaHome', self.javaHome) + if (prodMode == 'true'): + setOption('ServerStartMode', 'prod') + else: + setOption('ServerStartMode', 'dev') + set('Name', domainName) + + admin_port = int(adminListenPort) + ms_port = int(managedServerPort) + ms_count = int(managedCount) + + # Create Admin Server + # ======================= + print 'Creating Admin Server...' + cd('/Servers/AdminServer') + #set('ListenAddress', '%s-%s' % (domain_uid, admin_server_name_svc)) + set('ListenPort', admin_port) + set('Name', adminName) + + # Define the user password for weblogic + # ===================================== + cd('/Security/' + domainName + '/User/weblogic') + set('Name', user) + set('Password', password) + + # Create a cluster + # ====================== + print 'Creating cluster...' + cd('/') + cl=create(clusterName, 'Cluster') + + # Create managed servers + for index in range(0, ms_count): + cd('/') + msIndex = index+1 + cd('/') + name = '%s%s' % (managedNameBase, msIndex) + create(name, 'Server') + cd('/Servers/%s/' % name ) + print('managed server name is %s' % name); + set('ListenPort', ms_port) + set('NumOfRetriesBeforeMSIMode', 0) + set('RetryIntervalBeforeMSIMode', 1) + set('Cluster', clusterName) + + # Create Node Manager + # ======================= + print 'Creating Node Managers...' + for machine in self.MACHINES: + cd('/') + create(machine, 'Machine') + cd('Machine/' + machine) + create(machine, 'NodeManager') + cd('NodeManager/' + machine) + for param in self.MACHINES[machine]: + set(param, self.MACHINES[machine][param]) + + + setOption('OverwriteDomain', 'true') + domainHome = self.domainParentDir + '/' + domainName + print 'Will create Base domain at ' + domainHome + + print 'Writing base domain...' + writeDomain(domainHome) + closeTemplate() + print 'Base domain created at ' + domainHome + return domainHome + + + def extendDomain(self, domainHome, exposeAdminT3Channel, t3ChannelPublicAddress, + t3ChannelPort): + print 'Extending domain at ' + domainHome + readDomain(domainHome) + setOption('AppDir', self.domainParentDir + '/applications') + + print 'ExposeAdminT3Channel %s with %s:%s ' % (exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) + if 'true' == exposeAdminT3Channel: + self.enable_admin_channel(t3ChannelPublicAddress, t3ChannelPort) + + print 'Applying JRF templates...' + for extensionTemplate in self.JRF_12213_TEMPLATES['extensionTemplates']: + addTemplate(self.replaceTokens(extensionTemplate)) + + print 'Extension Templates added' + + print 'Preparing to update domain...' + updateDomain() + print 'Domain updated successfully' + closeDomain() + return + + + ########################################################################### + # Helper Methods # + ########################################################################### + + def validateDirectory(self, dirName, create=False): + directory = os.path.realpath(dirName) + if not os.path.exists(directory): + if create: + os.makedirs(directory) + else: + message = 'Directory ' + directory + ' does not exist' + raise WLSTException(message) + elif not os.path.isdir(directory): + message = 'Directory ' + directory + ' is not a directory' + raise WLSTException(message) + return self.fixupPath(directory) + + + def fixupPath(self, path): + result = path + if path is not None: + result = path.replace('\\', '/') + return result + + + def replaceTokens(self, path): + result = path + if path is not None: + result = path.replace('@@ORACLE_HOME@@', oracleHome) + return result + + def enable_admin_channel(self, admin_channel_address, admin_channel_port): + if admin_channel_address == None or admin_channel_port == 'None': + return + cd('/') + admin_server_name = get('AdminServerName') + print('setting admin server t3channel for ' + admin_server_name) + cd('/Servers/' + admin_server_name) + create('T3Channel', 'NetworkAccessPoint') + cd('/Servers/' + admin_server_name + '/NetworkAccessPoint/T3Channel') + set('ListenPort', int(admin_channel_port)) + set('PublicPort', int(admin_channel_port)) + set('PublicAddress', admin_channel_address) + +############################# +# Entry point to the script # +############################# + +def usage(): + print sys.argv[0] + ' -oh -jh -parent -name ' + \ + '-user -password ' + \ + '-rcuDb -rcuPrefix -rcuSchemaPwd ' \ + '-adminListenPort -adminName ' \ + '-managedNameBase -managedServerPort -prodMode ' \ + '-managedServerCount -clusterName ' \ + '-exposeAdminT3Channel -t3ChannelPublicAddress
' \ + '-t3ChannelPort ' + sys.exit(0) + +# Uncomment for Debug only +#print str(sys.argv[0]) + " called with the following sys.argv array:" +#for index, arg in enumerate(sys.argv): +# print "sys.argv[" + str(index) + "] = " + str(sys.argv[index]) + +if len(sys.argv) < 16: + usage() + +#oracleHome will be passed by command line parameter -oh. +oracleHome = None +#javaHome will be passed by command line parameter -jh. +javaHome = None +#domainParentDir will be passed by command line parameter -parent. +domainParentDir = None +#domainUser is hard-coded to weblogic. You can change to other name of your choice. Command line paramter -user. +domainUser = 'weblogic' +#domainPassword will be passed by Command line parameter -password. +domainPassword = None +#rcuDb will be passed by command line parameter -rcuDb. +rcuDb = None +#change rcuSchemaPrefix to your infra schema prefix. Command line parameter -rcuPrefix. +rcuSchemaPrefix = 'DEV12' +#change rcuSchemaPassword to your infra schema password. Command line parameter -rcuSchemaPwd. +rcuSchemaPassword = None +exposeAdminT3Channel = None +t3ChannelPort = None +t3ChannelPublicAddress = None +i = 1 +while i < len(sys.argv): + if sys.argv[i] == '-oh': + oracleHome = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-jh': + javaHome = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-parent': + domainParentDir = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-name': + domainName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-user': + domainUser = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-password': + domainPassword = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuDb': + rcuDb = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuPrefix': + rcuSchemaPrefix = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-rcuSchemaPwd': + rcuSchemaPassword = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-adminListenPort': + adminListenPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-adminName': + adminName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedNameBase': + managedNameBase = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedServerPort': + managedServerPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-prodMode': + prodMode = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-managedServerCount': + managedCount = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-clusterName': + clusterName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-t3ChannelPublicAddress': + t3ChannelPublicAddress = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-t3ChannelPort': + t3ChannelPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-exposeAdminT3Channel': + exposeAdminT3Channel = sys.argv[i + 1] + i += 2 + else: + print 'Unexpected argument switch at position ' + str(i) + ': ' + str(sys.argv[i]) + usage() + sys.exit(1) + +provisioner = Infra12213Provisioner(oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName) +provisioner.createInfraDomain(domainName, domainUser, domainPassword, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, + clusterName, exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) diff --git a/OracleWebCenterPortal/kubernetes/common/domain-template.yaml b/OracleWebCenterPortal/kubernetes/common/domain-template.yaml new file mode 100644 index 000000000..2d081de7d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/common/domain-template.yaml @@ -0,0 +1,119 @@ +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# This is an example of how to define a Domain resource. +# +apiVersion: "weblogic.oracle/v8" +kind: Domain +metadata: + name: %DOMAIN_UID% + namespace: %NAMESPACE% + labels: + weblogic.domainUID: %DOMAIN_UID% +spec: + # The WebLogic Domain Home + domainHome: %DOMAIN_HOME% + + # The domain home source type + # Set to PersistentVolume for domain-in-pv, Image for domain-in-image, or FromModel for model-in-image + domainHomeSourceType: %DOMAIN_HOME_SOURCE_TYPE% + + # The WebLogic Server image that the Operator uses to start the domain + image: "%WEBLOGIC_IMAGE%" + + # imagePullPolicy defaults to "Always" if image version is :latest + imagePullPolicy: "%WEBLOGIC_IMAGE_PULL_POLICY%" + + # Identify which Secret contains the credentials for pulling an image + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%imagePullSecrets: + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%- name: %WEBLOGIC_IMAGE_PULL_SECRET_NAME% + + # Identify which Secret contains the WebLogic Admin credentials (note that there is an example of + # how to create that Secret at the end of this file) + webLogicCredentialsSecret: + name: %WEBLOGIC_CREDENTIALS_SECRET_NAME% + + # Whether to include the server out file into the pod's stdout, default is true + includeServerOutInPodLog: %INCLUDE_SERVER_OUT_IN_POD_LOG% + + # Whether to enable log home + %LOG_HOME_ON_PV_PREFIX%logHomeEnabled: %LOG_HOME_ENABLED% + + # Whether to write HTTP access log file to log home + %LOG_HOME_ON_PV_PREFIX%httpAccessLogInLogHome: %HTTP_ACCESS_LOG_IN_LOG_HOME% + + # The in-pod location for domain log, server logs, server out, introspector out, and Node Manager log files + %LOG_HOME_ON_PV_PREFIX%logHome: %LOG_HOME% + # An (optional) in-pod location for data storage of default and custom file stores. + # If not specified or the value is either not set or empty (e.g. dataHome: "") then the + # data storage directories are determined from the WebLogic domain home configuration. + dataHome: "%DATA_HOME%" + + + # serverStartPolicy legal values are "NEVER", "IF_NEEDED", or "ADMIN_ONLY" + # This determines which WebLogic Servers the Operator will start up when it discovers this Domain + # - "NEVER" will not start any server in the domain + # - "ADMIN_ONLY" will start up only the administration server (no managed servers will be started) + # - "IF_NEEDED" will start all non-clustered servers, including the administration server and clustered servers up to the replica count + serverStartPolicy: "%SERVER_START_POLICY%" + + serverPod: + # an (optional) list of environment variable to be set on the servers + env: + - name: JAVA_OPTIONS + value: "%JAVA_OPTIONS%" + - name: USER_MEM_ARGS + value: "-Djava.security.egd=file:/dev/./urandom -Xms256m -Xmx512m " + %OPTIONAL_SERVERPOD_RESOURCES% + %LOG_HOME_ON_PV_PREFIX%volumes: + %LOG_HOME_ON_PV_PREFIX%- name: weblogic-domain-storage-volume + %LOG_HOME_ON_PV_PREFIX% persistentVolumeClaim: + %LOG_HOME_ON_PV_PREFIX% claimName: %DOMAIN_PVC_NAME% + %LOG_HOME_ON_PV_PREFIX%volumeMounts: + %LOG_HOME_ON_PV_PREFIX%- mountPath: %DOMAIN_ROOT_DIR% + %LOG_HOME_ON_PV_PREFIX% name: weblogic-domain-storage-volume + + # adminServer is used to configure the desired behavior for starting the administration server. + adminServer: + # serverStartState legal values are "RUNNING" or "ADMIN" + # "RUNNING" means the listed server will be started up to "RUNNING" mode + # "ADMIN" means the listed server will be start up to "ADMIN" mode + serverStartState: "RUNNING" + %EXPOSE_ANY_CHANNEL_PREFIX%adminService: + %EXPOSE_ANY_CHANNEL_PREFIX% channels: + # The Admin Server's NodePort + %EXPOSE_ADMIN_PORT_PREFIX% - channelName: default + %EXPOSE_ADMIN_PORT_PREFIX% nodePort: %ADMIN_NODE_PORT% + # Uncomment to export the T3Channel as a service + %EXPOSE_T3_CHANNEL_PREFIX% - channelName: T3Channel + + # clusters is used to configure the desired behavior for starting member servers of a cluster. + # If you use this entry, then the rules will be applied to ALL servers that are members of the named clusters. + clusters: + - clusterName: %CLUSTER_NAME% + serverStartState: "RUNNING" + serverPod: + # Instructs Kubernetes scheduler to prefer nodes for new cluster members where there are not + # already members of the same cluster. + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: "weblogic.clusterName" + operator: In + values: + - $(CLUSTER_NAME) + topologyKey: "kubernetes.io/hostname" + replicas: %INITIAL_MANAGED_SERVER_REPLICAS% + # The number of managed servers to start for unlisted clusters + # replicas: 1 + + # Istio + %ISTIO_PREFIX%configuration: + %ISTIO_PREFIX% istio: + %ISTIO_PREFIX% enabled: %ISTIO_ENABLED% + %ISTIO_PREFIX% readinessPort: %ISTIO_READINESS_PORT% + diff --git a/OracleWebCenterPortal/kubernetes/common/jrf-domain-template.yaml b/OracleWebCenterPortal/kubernetes/common/jrf-domain-template.yaml new file mode 100644 index 000000000..ccd35b84f --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/common/jrf-domain-template.yaml @@ -0,0 +1,123 @@ +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# This is an example of how to define a Domain resource. +# +apiVersion: "weblogic.oracle/v8" +kind: Domain +metadata: + name: %DOMAIN_UID% + namespace: %NAMESPACE% + labels: + weblogic.domainUID: %DOMAIN_UID% +spec: + # The WebLogic Domain Home + domainHome: %DOMAIN_HOME% + + # The domain home source type + # Set to PersistentVolume for domain-in-pv, Image for domain-in-image, or FromModel for model-in-image + domainHomeSourceType: %DOMAIN_HOME_SOURCE_TYPE% + + # The WebLogic Server image that the Operator uses to start the domain + image: "%WEBLOGIC_IMAGE%" + + # imagePullPolicy defaults to "Always" if image version is :latest + imagePullPolicy: "%WEBLOGIC_IMAGE_PULL_POLICY%" + + # Identify which Secret contains the credentials for pulling an image + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%imagePullSecrets: + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%- name: %WEBLOGIC_IMAGE_PULL_SECRET_NAME% + + # Identify which Secret contains the WebLogic Admin credentials (note that there is an example of + # how to create that Secret at the end of this file) + webLogicCredentialsSecret: + name: %WEBLOGIC_CREDENTIALS_SECRET_NAME% + + # Whether to include the server out file into the pod's stdout, default is true + includeServerOutInPodLog: %INCLUDE_SERVER_OUT_IN_POD_LOG% + + # Whether to enable log home + %LOG_HOME_ON_PV_PREFIX%logHomeEnabled: %LOG_HOME_ENABLED% + + # Whether to write HTTP access log file to log home + %LOG_HOME_ON_PV_PREFIX%httpAccessLogInLogHome: %HTTP_ACCESS_LOG_IN_LOG_HOME% + + # The in-pod location for domain log, server logs, server out, introspector out, and Node Manager log files + %LOG_HOME_ON_PV_PREFIX%logHome: %LOG_HOME% + # An (optional) in-pod location for data storage of default and custom file stores. + # If not specified or the value is either not set or empty (e.g. dataHome: "") then the + # data storage directories are determined from the WebLogic domain home configuration. + dataHome: "%DATA_HOME%" + + # serverStartPolicy legal values are "NEVER", "IF_NEEDED", or "ADMIN_ONLY" + # This determines which WebLogic Servers the Operator will start up when it discovers this Domain + # - "NEVER" will not start any server in the domain + # - "ADMIN_ONLY" will start up only the administration server (no managed servers will be started) + # - "IF_NEEDED" will start all non-clustered servers, including the administration server and clustered servers up to the replica count + serverStartPolicy: "%SERVER_START_POLICY%" + + serverPod: + # an (optional) list of environment variable to be set on the servers + env: + - name: JAVA_OPTIONS + value: "%JAVA_OPTIONS%" + - name: USER_MEM_ARGS + value: "-Djava.security.egd=file:/dev/./urandom -Xms256m -Xmx1024m " + %OPTIONAL_SERVERPOD_RESOURCES% + %LOG_HOME_ON_PV_PREFIX%volumes: + %LOG_HOME_ON_PV_PREFIX%- name: weblogic-domain-storage-volume + %LOG_HOME_ON_PV_PREFIX% persistentVolumeClaim: + %LOG_HOME_ON_PV_PREFIX% claimName: %DOMAIN_PVC_NAME% + %LOG_HOME_ON_PV_PREFIX%volumeMounts: + %LOG_HOME_ON_PV_PREFIX%- mountPath: %DOMAIN_ROOT_DIR% + %LOG_HOME_ON_PV_PREFIX% name: weblogic-domain-storage-volume + + # adminServer is used to configure the desired behavior for starting the administration server. + adminServer: + # serverStartState legal values are "RUNNING" or "ADMIN" + # "RUNNING" means the listed server will be started up to "RUNNING" mode + # "ADMIN" means the listed server will be start up to "ADMIN" mode + serverStartState: "RUNNING" + %EXPOSE_ANY_CHANNEL_PREFIX%adminService: + %EXPOSE_ANY_CHANNEL_PREFIX% channels: + # The Admin Server's NodePort + %EXPOSE_ADMIN_PORT_PREFIX% - channelName: default + %EXPOSE_ADMIN_PORT_PREFIX% nodePort: %ADMIN_NODE_PORT% + # Uncomment to export the T3Channel as a service + %EXPOSE_T3_CHANNEL_PREFIX% - channelName: T3Channel + serverPod: + # an (optional) list of environment variable to be set on the admin servers + env: + - name: USER_MEM_ARGS + value: "-Djava.security.egd=file:/dev/./urandom -Xms512m -Xmx1024m " + + # clusters is used to configure the desired behavior for starting member servers of a cluster. + # If you use this entry, then the rules will be applied to ALL servers that are members of the named clusters. + clusters: + - clusterName: %CLUSTER_NAME% + serverStartState: "RUNNING" + serverPod: + # Instructs Kubernetes scheduler to prefer nodes for new cluster members where there are not + # already members of the same cluster. + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: "weblogic.clusterName" + operator: In + values: + - $(CLUSTER_NAME) + topologyKey: "kubernetes.io/hostname" + replicas: %INITIAL_MANAGED_SERVER_REPLICAS% + # The number of managed servers to start for unlisted clusters + # replicas: 1 + + # Istio + %ISTIO_PREFIX%configuration: + %ISTIO_PREFIX% istio: + %ISTIO_PREFIX% enabled: %ISTIO_ENABLED% + %ISTIO_PREFIX% readinessPort: %ISTIO_READINESS_PORT% + diff --git a/OracleWebCenterPortal/kubernetes/common/utility.sh b/OracleWebCenterPortal/kubernetes/common/utility.sh new file mode 100644 index 000000000..979207be2 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/common/utility.sh @@ -0,0 +1,928 @@ +#!/usr/bin/env bash +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# +# Utility functions that are shared by multiple scripts +# + +# +# Function to exit and print an error message +# $1 - text of message +function fail { + printError $* + exit 1 +} + +# Function to print an error message +function printError { + echo [ERROR] $* +} + +# Function to see if there is more than 1 input file. +# This could happen if the user has a properties file from +# running wdt discover domain on a on-prem domain +function checkInputFiles { + if [[ "${valuesInputFile}" =~ [,] ]] ; then + echo "Found a comma separated list of input files" + IFS=',' + read -a temp <<< "${valuesInputFile}" + + # We want to keep valuesInputFile pointing to the yaml since + # the validate function expects it. + local extension=$(echo "${temp[0]}" | sed 's/^.*\.//') + if [ ${extension} == 'yaml' ]; then + valuesInputFile=${temp[0]} + valuesInputFile1=${temp[1]} + else + valuesInputFile=${temp[1]} + valuesInputFile1=${temp[0]} + fi + fi +} + +# +# Function to parse a yaml file and generate the bash exports +# $1 - Input filename +# $2 - Output filename +function parseYaml { + local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') + sed -ne "s|^\($s\):|\1|" \ + -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | + awk -F$fs '{ + if (length($3) > 0) { + # javaOptions may contain tokens that are not allowed in export command + # we need to handle it differently. + if ($2=="javaOptions") { + printf("%s=%s\n", $2, $3); + } else { + printf("export %s=\"%s\"\n", $2, $3); + } + } + }' > $2 +} + +# +# Function to parse a properties file and generate the bash exports +# $1 - Input filename +# $2 - Output filename +function parseProperties { + while IFS='=' read -r key value + do + echo "export ${key}=\"${value}\"" >> $2 + done < $1 +} + +# +# Function to remove a file if it exists +# +function removeFileIfExists { + if [ -f $1 ]; then + rm $1 + fi +} + +# +# Function to parse the common parameter inputs file +# +function parseCommonInputs { + exportValuesFile=$(mktemp /tmp/export-values-XXXXXXXXX.sh) + tmpFile=$(mktemp /tmp/javaoptions_tmp-XXXXXXXXX.dat) + parseYaml ${valuesInputFile} ${exportValuesFile} + + if [ ! -z ${valuesInputFile1} ]; then + parseProperties ${valuesInputFile1} ${exportValuesFile} + fi + + if [ ! -f ${exportValuesFile} ]; then + echo Unable to locate the parsed output of ${valuesInputFile}. + fail 'The file ${exportValuesFile} could not be found.' + fi + + # Define the environment variables that will be used to fill in template values + echo Input parameters being used + cat ${exportValuesFile} + echo + + # If we have 2 input files, we need to create a combined inputs file + # exportsValueFile contains all the properties already + # We just need to remove the term export from the file + if [ ! -z ${valuesInputFile1} ]; then + propsFile="domain.properties" + cat ${exportValuesFile} > ${propsFile} + sed -i 's/export //g' ${propsFile} + sed -i 's/"//g' ${propsFile} + valuesInputFile=${propsFile} + cat ${valuesInputFile} + fi + + # javaOptions may contain tokens that are not allowed in export command + # we need to handle it differently. + # we set the javaOptions variable that can be used later + tmpStr=`grep "javaOptions" ${exportValuesFile}` + javaOptions=${tmpStr//"javaOptions="/} + + # We exclude javaOptions from the exportValuesFile + grep -v "javaOptions" ${exportValuesFile} > ${tmpFile} + source ${tmpFile} + + rm ${exportValuesFile} ${tmpFile} +} + +# +# Function to delete a kubernetes object +# $1 object type +# $2 object name +# $3 yaml file +function deleteK8sObj { + # If the yaml file does not exist yet, unable to do the delete + if [ ! -f $3 ]; then + fail "Unable to delete object type $1 with name $2 because file $3 does not exist" + fi + + echo Checking if object type $1 with name $2 exists + K8SOBJ=`kubectl get $1 -n ${namespace} | grep $2 | wc | awk ' { print $1; }'` + if [ "${K8SOBJ}" = "1" ]; then + echo Deleting $2 using $3 + kubectl delete -f $3 + fi +} + +# +# Function to lowercase a value +# $1 - value to convert to lowercase +function toLower { + local lc=`echo $1 | tr "[:upper:]" "[:lower:]"` + echo "$lc" +} + +# +# Function to lowercase a value and make it a legal DNS1123 name +# $1 - value to convert to lowercase +function toDNS1123Legal { + local val=`echo $1 | tr "[:upper:]" "[:lower:]"` + val=${val//"_"/"-"} + echo "$val" +} + +# +# Check the state of a persistent volume. +# $1 - name of volume +# $2 - expected state of volume +function checkPvState { + + echo "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 10 ]; do + attempts=$((attempts + 1)) + sleep 1 + pv_state=`kubectl get pv $1 -o jsonpath='{.status.phase}'` + done + if [ "$pv_state" != "$2" ]; then + fail "The persistent volume state should be $2 but is $pv_state" + fi +} + +# +# Function to check if a persistent volume exists +# $1 - name of volume +function checkPvExists { + + echo "Checking if the persistent volume ${1} exists" + PV_EXISTS=`kubectl get pv | grep ${1} | wc | awk ' { print $1; } '` + if [ "${PV_EXISTS}" = "1" ]; then + echo "The persistent volume ${1} already exists" + PV_EXISTS="true" + else + echo "The persistent volume ${1} does not exist" + PV_EXISTS="false" + fi +} + +# +# Function to check if a persistent volume claim exists +# $1 - name of persistent volume claim +# $2 - NameSpace +function checkPvcExists { + echo "Checking if the persistent volume claim ${1} in NameSpace ${2} exists" + PVC_EXISTS=`kubectl get pvc -n ${2} | grep ${1} | wc | awk ' { print $1; } '` + if [ "${PVC_EXISTS}" = "1" ]; then + echo "The persistent volume claim ${1} already exists in NameSpace ${2}" + PVC_EXISTS="true" + else + echo "The persistent volume claim ${1} does not exist in NameSpace ${2}" + PVC_EXISTS="false" + fi +} + +# Copy the inputs file from the command line into the output directory +# for the domain/operator unless the output directory already has an +# inputs file and the file is the same as the one from the commandline. +# $1 the inputs file from the command line +# $2 the file in the output directory that needs to be made the same as $1 +function copyInputsFileToOutputDirectory { + local from=$1 + local to=$2 + local doCopy="true" + if [ -f "${to}" ]; then + local difference=`diff ${from} ${to}` + if [ -z "${difference}" ]; then + # the output file already exists and is the same as the inputs file. + # don't make a copy. + doCopy="false" + fi + fi + if [ "${doCopy}" = "true" ]; then + cp ${from} ${to} + fi +} + +# +# Function to obtain the IP address of the kubernetes cluster. This information +# is used to form the URL's for accessing services that were deployed. +# +function getKubernetesClusterIP { + + # Get name of the current context + local CUR_CTX=`kubectl config current-context | awk ' { print $1; } '` + + # Get the name of the current cluster + local CUR_CLUSTER_CMD="kubectl config view -o jsonpath='{.contexts[?(@.name == \"${CUR_CTX}\")].context.cluster}' | awk ' { print $1; } '" + local CUR_CLUSTER=`eval ${CUR_CLUSTER_CMD}` + + # Get the server address for the current cluster + local SVR_ADDR_CMD="kubectl config view -o jsonpath='{.clusters[?(@.name == \"${CUR_CLUSTER}\")].cluster.server}' | awk ' { print $1; } '" + local SVR_ADDR=`eval ${SVR_ADDR_CMD}` + + # Server address is expected to be of the form http://address:port. Delimit + # string on the colon to obtain the address. + local array=(${SVR_ADDR//:/ }) + K8S_IP="${array[1]/\/\//}" + +} + +# +# Function to set the serverPodResources variable for including into the generated +# domain.yaml, base on the serverPod resource requests and limits input values, +# if specified. +# The serverPodResources variable remains unset if none of the input values are provided. +# +function buildServerPodResources { + + if [ -n "${serverPodMemoryRequest}" ]; then + local memoryRequest=" memory\: \"${serverPodMemoryRequest}\"\n" + fi + if [ -n "${serverPodCpuRequest}" ]; then + local cpuRequest=" cpu\: \"${serverPodCpuRequest}\"\n" + fi + if [ -n "${memoryRequest}" ] || [ -n "${cpuRequest}" ]; then + local requests=" requests\: \n$memoryRequest $cpuRequest" + fi + + if [ -n "${serverPodMemoryLimit}" ]; then + local memoryLimit=" memory\: \"${serverPodMemoryLimit}\"\n" + fi + if [ -n "${serverPodCpuLimit}" ]; then + local cpuLimit=" cpu\: \"${serverPodCpuLimit}\"\n" + fi + if [ -n "${memoryLimit}" ] || [ -n "${cpuLimit}" ]; then + local limits=" limits\: \n$memoryLimit $cpuLimit" + fi + + if [ -n "${requests}" ] || [ -n "${limits}" ]; then + # build resources element and remove last '\n' + serverPodResources=$(echo "resources\:\n${requests}${limits}" | sed -e 's/\\n$//') + fi +} + +# +# Function to generate the properties and yaml files for creating a domain +# +function createFiles { + + update=false + if [ "$#" == 1 ]; then + echo Trying to update the domain + update=true + fi + + # Make sure the output directory has a copy of the inputs file. + # The user can either pre-create the output directory, put the inputs + # file there, and create the domain from it, or the user can put the + # inputs file some place else and let this script create the output directory + # (if needed) and copy the inputs file there. + echo createFiles - valuesInputFile is ${valuesInputFile} + copyInputsFileToOutputDirectory ${valuesInputFile} "${domainOutputDir}/create-domain-inputs.yaml" + + if [ "${domainHomeInImage}" == "true" ]; then + if [ -z "${domainHomeImageBase}" ]; then + fail "Please specify domainHomeImageBase in your input YAML" + fi + else + if [ -z "${image}" ]; then + fail "Please specify image in your input YAML" + fi + fi + + dcrOutput="${domainOutputDir}/domain.yaml" + + domainName=${domainUID} + + enabledPrefix="" # uncomment the feature + disabledPrefix="# " # comment out the feature + + exposeAnyChannelPrefix="${disabledPrefix}" + if [ "${exposeAdminT3Channel}" = true ]; then + exposeAdminT3ChannelPrefix="${enabledPrefix}" + exposeAnyChannelPrefix="${enabledPrefix}" + # set t3PublicAddress if not set + if [ -z "${t3PublicAddress}" ]; then + getKubernetesClusterIP + t3PublicAddress="${K8S_IP}" + fi + else + exposeAdminT3ChannelPrefix="${disabledPrefix}" + fi + + if [ "${exposeAdminNodePort}" = true ]; then + exposeAdminNodePortPrefix="${enabledPrefix}" + exposeAnyChannelPrefix="${enabledPrefix}" + else + exposeAdminNodePortPrefix="${disabledPrefix}" + fi + + if [ "${istioEnabled}" == "true" ]; then + istioPrefix="${enabledPrefix}" + else + istioPrefix="${disabledPrefix}" + fi + + # The FromModel, MII (model-in-image), and WDT_DOMAIN_TYPE updates in this script + # must remain even though they are not referenced by a sample. They're used by the + # Operator integration test code. If you're interested in MII, + # see './kubernetes/samples/scripts/create-weblogic-domain/model-in-image'. + + # MII settings are used for model-in-image integration testing + if [ "${domainHomeSourceType}" == "FromModel" ]; then + miiPrefix="${enabledPrefix}" + else + miiPrefix="${disabledPrefix}" + fi + + # MII settings are used for model-in-image integration testing + if [ -z "${miiConfigMap}" ]; then + miiConfigMapPrefix="${disabledPrefix}" + else + miiConfigMapPrefix="${enabledPrefix}" + fi + + # For some parameters, use the default value if not defined. + if [ -z "${domainPVMountPath}" ]; then + domainPVMountPath="/shared" + fi + + if [ -z "${logHome}" ]; then + logHome="${domainPVMountPath}/logs/${domainUID}" + fi + + if [ -z "${httpAccessLogInLogHome}" ]; then + httpAccessLogInLogHome="true" + fi + + if [ -z "${dataHome}" ]; then + dataHome="" + fi + + if [ -z "${persistentVolumeClaimName}" ]; then + persistentVolumeClaimName="${domainUID}-weblogic-sample-pvc" + fi + + if [ -z "${weblogicCredentialsSecretName}" ]; then + weblogicCredentialsSecretName="${domainUID}-weblogic-credentials" + fi + + if [ "${domainHomeInImage}" == "true" ]; then + domainPropertiesOutput="${domainOutputDir}/domain.properties" + domainHome="${domainHome:-/u01/oracle/user_projects/domains/${domainName}}" + + # Generate the properties file that will be used when creating the weblogic domain + echo Generating ${domainPropertiesOutput} from ${domainPropertiesInput} + + cp ${domainPropertiesInput} ${domainPropertiesOutput} + sed -i -e "s:%DOMAIN_NAME%:${domainName}:g" ${domainPropertiesOutput} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_PORT%:${adminPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_SERVER_SSL_PORT%:${adminServerSSLPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_SERVER_NAME%:${adminServerName}:g" ${domainPropertiesOutput} + sed -i -e "s:%MANAGED_SERVER_PORT%:${managedServerPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%MANAGED_SERVER_SSL_PORT%:${managedServerSSLPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%MANAGED_SERVER_NAME_BASE%:${managedServerNameBase}:g" ${domainPropertiesOutput} + sed -i -e "s:%CONFIGURED_MANAGED_SERVER_COUNT%:${configuredManagedServerCount}:g" ${domainPropertiesOutput} + sed -i -e "s:%CLUSTER_NAME%:${clusterName}:g" ${domainPropertiesOutput} + sed -i -e "s:%SSL_ENABLED%:${sslEnabled}:g" ${domainPropertiesOutput} + sed -i -e "s:%PRODUCTION_MODE_ENABLED%:${productionModeEnabled}:g" ${domainPropertiesOutput} + sed -i -e "s:%CLUSTER_TYPE%:${clusterType}:g" ${domainPropertiesOutput} + sed -i -e "s;%JAVA_OPTIONS%;${javaOptions};g" ${domainPropertiesOutput} + sed -i -e "s:%T3_CHANNEL_PORT%:${t3ChannelPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%T3_PUBLIC_ADDRESS%:${t3PublicAddress}:g" ${domainPropertiesOutput} + sed -i -e "s:%EXPOSE_T3_CHANNEL%:${exposeAdminT3Channel}:g" ${domainPropertiesOutput} + sed -i -e "s:%FMW_DOMAIN_TYPE%:${fmwDomainType}:g" ${domainPropertiesOutput} + sed -i -e "s:%WDT_DOMAIN_TYPE%:${wdtDomainType}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_USER_NAME%:${username}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_USER_PASS%:${password}:g" ${domainPropertiesOutput} + sed -i -e "s:%RCU_SCHEMA_PREFIX%:${rcuSchemaPrefix}:g" ${domainPropertiesOutput} + sed -i -e "s:%RCU_SCHEMA_PASSWORD%:${rcuSchemaPassword}:g" ${domainPropertiesOutput} + sed -i -e "s|%RCU_DB_CONN_STRING%|${rcuDatabaseURL}|g" ${domainPropertiesOutput} + + if [ -z "${image}" ]; then + # calculate the internal name to tag the generated image + defaultImageName="domain-home-in-image" + baseTag=${domainHomeImageBase#*:} + defaultImageName=${defaultImageName}:${baseTag:-"latest"} + sed -i -e "s|%IMAGE_NAME%|${defaultImageName}|g" ${domainPropertiesOutput} + export BUILD_IMAGE_TAG=${defaultImageName} + else + sed -i -e "s|%IMAGE_NAME%|${image}|g" ${domainPropertiesOutput} + export BUILD_IMAGE_TAG=${image} + fi + else + # we're in the domain in PV case + + wdtVersion="${WDT_VERSION:-${wdtVersion}}" + httpsProxy="${https_proxy}" + + createJobOutput="${domainOutputDir}/create-domain-job.yaml" + deleteJobOutput="${domainOutputDir}/delete-domain-job.yaml" + + if [ -z "${domainHome}" ]; then + domainHome="${domainPVMountPath}/domains/${domainUID}" + fi + + # Use the default value if not defined. + if [ -z "${createDomainScriptsMountPath}" ]; then + createDomainScriptsMountPath="/u01/weblogic" + fi + + if [ "${update}" == "true" ]; then + createDomainScriptName="update-domain-job.sh" + elif [ -z "${createDomainScriptName}" ]; then + createDomainScriptName="create-domain-job.sh" + fi + echo createDomainScriptName is ${createDomainScriptName} + + # Must escape the ':' value in image for sed to properly parse and replace + image=$(echo ${image} | sed -e "s/\:/\\\:/g") + + # Generate the yaml to create the kubernetes job that will create the weblogic domain + echo Generating ${createJobOutput} + + cp ${createJobInput} ${createJobOutput} + sed -i -e "s:%NAMESPACE%:$namespace:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_CREDENTIALS_SECRET_NAME%:${weblogicCredentialsSecretName}:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE%:${image}:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_POLICY%:${imagePullPolicy}:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_NAME%:${imagePullSecretName}:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%:${imagePullSecretPrefix}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_UID%:${domainUID}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_NAME%:${domainName}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${createJobOutput} + sed -i -e "s:%SSL_ENABLED%:${sslEnabled}:g" ${createJobOutput} + sed -i -e "s:%PRODUCTION_MODE_ENABLED%:${productionModeEnabled}:g" ${createJobOutput} + sed -i -e "s:%ADMIN_SERVER_NAME%:${adminServerName}:g" ${createJobOutput} + sed -i -e "s:%ADMIN_SERVER_NAME_SVC%:${adminServerNameSVC}:g" ${createJobOutput} + sed -i -e "s:%ADMIN_PORT%:${adminPort}:g" ${createJobOutput} + sed -i -e "s:%ADMIN_SERVER_SSL_PORT%:${adminServerSSLPort}:g" ${createJobOutput} + sed -i -e "s:%CONFIGURED_MANAGED_SERVER_COUNT%:${configuredManagedServerCount}:g" ${createJobOutput} + sed -i -e "s:%MANAGED_SERVER_NAME_BASE%:${managedServerNameBase}:g" ${createJobOutput} + sed -i -e "s:%MANAGED_SERVER_NAME_BASE_SVC%:${managedServerNameBaseSVC}:g" ${createJobOutput} + sed -i -e "s:%MANAGED_SERVER_PORT%:${managedServerPort}:g" ${createJobOutput} + sed -i -e "s:%MANAGED_SERVER_SSL_PORT%:${managedServerSSLPort}:g" ${createJobOutput} + sed -i -e "s:%T3_CHANNEL_PORT%:${t3ChannelPort}:g" ${createJobOutput} + sed -i -e "s:%T3_PUBLIC_ADDRESS%:${t3PublicAddress}:g" ${createJobOutput} + sed -i -e "s:%CLUSTER_NAME%:${clusterName}:g" ${createJobOutput} + sed -i -e "s:%CLUSTER_TYPE%:${clusterType}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_PVC_NAME%:${persistentVolumeClaimName}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_ROOT_DIR%:${domainPVMountPath}:g" ${createJobOutput} + sed -i -e "s:%CREATE_DOMAIN_SCRIPT_DIR%:${createDomainScriptsMountPath}:g" ${createJobOutput} + sed -i -e "s:%CREATE_DOMAIN_SCRIPT%:${createDomainScriptName}:g" ${createJobOutput} + # extra entries for FMW Infra domains + sed -i -e "s:%RCU_CREDENTIALS_SECRET_NAME%:${rcuCredentialsSecret}:g" ${createJobOutput} + sed -i -e "s:%CUSTOM_RCUPREFIX%:${rcuSchemaPrefix}:g" ${createJobOutput} + sed -i -e "s|%CUSTOM_CONNECTION_STRING%|${rcuDatabaseURL}|g" ${createJobOutput} + sed -i -e "s:%EXPOSE_T3_CHANNEL_PREFIX%:${exposeAdminT3Channel}:g" ${createJobOutput} + sed -i -e "s:%FRONTEND_HOST%:${frontEndHost}:g" ${createJobOutput} + sed -i -e "s:%FRONTEND_PORT%:${frontEndPort}:g" ${createJobOutput} + # entries for Istio + sed -i -e "s:%ISTIO_PREFIX%:${istioPrefix}:g" ${createJobOutput} + sed -i -e "s:%ISTIO_ENABLED%:${istioEnabled}:g" ${createJobOutput} + sed -i -e "s:%ISTIO_READINESS_PORT%:${istioReadinessPort}:g" ${createJobOutput} + sed -i -e "s:%WDT_VERSION%:${wdtVersion}:g" ${createJobOutput} + sed -i -e "s|%DOMAIN_TYPE%|${domain_type}|g" ${createJobOutput} + sed -i -e "s|%PROXY_VAL%|${httpsProxy}|g" ${createJobOutput} + + # Generate the yaml to create the kubernetes job that will delete the weblogic domain_home folder + echo Generating ${deleteJobOutput} + + cp ${deleteJobInput} ${deleteJobOutput} + sed -i -e "s:%NAMESPACE%:$namespace:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE%:${image}:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_POLICY%:${imagePullPolicy}:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_CREDENTIALS_SECRET_NAME%:${weblogicCredentialsSecretName}:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_NAME%:${imagePullSecretName}:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%:${imagePullSecretPrefix}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_UID%:${domainUID}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_NAME%:${domainName}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_PVC_NAME%:${persistentVolumeClaimName}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_ROOT_DIR%:${domainPVMountPath}:g" ${deleteJobOutput} + fi + + if [ "${domainHomeSourceType}" == "FromModel" ]; then + echo domainHomeSourceType is FromModel + # leave domainHomeSourceType to FromModel + if [ "${logHomeOnPV}" == "true" ]; then + logHomeOnPVPrefix="${enabledPrefix}" + else + logHomeOnPVPrefix="${disabledPrefix}" + fi + elif [ "${domainHomeInImage}" == "true" ]; then + domainHomeSourceType="Image" + if [ "${logHomeOnPV}" == "true" ]; then + logHomeOnPVPrefix="${enabledPrefix}" + else + logHomeOnPVPrefix="${disabledPrefix}" + fi + else + domainHomeSourceType="PersistentVolume" + logHomeOnPVPrefix="${enabledPrefix}" + logHomeOnPV=true + fi + + # Generate the yaml file for creating the domain resource + # We want to use wdt's extractDomainResource.sh to get the domain resource + # for domain on pv use case. For others, generate domain resource here + + if [ "${domainHomeSourceType}" != "PersistentVolume" ] || [ "${wdtDomainType}" != "WLS" ] || + [ "${useWdt}" != true ]; then + echo Generating ${dcrOutput} + + cp ${dcrInput} ${dcrOutput} + sed -i -e "s:%DOMAIN_UID%:${domainUID}:g" ${dcrOutput} + sed -i -e "s:%NAMESPACE%:$namespace:g" ${dcrOutput} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${dcrOutput} + sed -i -e "s:%DOMAIN_HOME_SOURCE_TYPE%:${domainHomeSourceType}:g" ${dcrOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_POLICY%:${imagePullPolicy}:g" ${dcrOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%:${imagePullSecretPrefix}:g" ${dcrOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_NAME%:${imagePullSecretName}:g" ${dcrOutput} + sed -i -e "s:%WEBLOGIC_CREDENTIALS_SECRET_NAME%:${weblogicCredentialsSecretName}:g" ${dcrOutput} + sed -i -e "s:%INCLUDE_SERVER_OUT_IN_POD_LOG%:${includeServerOutInPodLog}:g" ${dcrOutput} + sed -i -e "s:%LOG_HOME_ON_PV_PREFIX%:${logHomeOnPVPrefix}:g" ${dcrOutput} + sed -i -e "s:%LOG_HOME_ENABLED%:${logHomeOnPV}:g" ${dcrOutput} + sed -i -e "s:%LOG_HOME%:${logHome}:g" ${dcrOutput} + sed -i -e "s:%HTTP_ACCESS_LOG_IN_LOG_HOME%:${httpAccessLogInLogHome}:g" ${dcrOutput} + sed -i -e "s:%DATA_HOME%:${dataHome}:g" ${dcrOutput} + sed -i -e "s:%SERVER_START_POLICY%:${serverStartPolicy}:g" ${dcrOutput} + sed -i -e "s;%JAVA_OPTIONS%;${javaOptions};g" ${dcrOutput} + sed -i -e "s:%DOMAIN_PVC_NAME%:${persistentVolumeClaimName}:g" ${dcrOutput} + sed -i -e "s:%DOMAIN_ROOT_DIR%:${domainPVMountPath}:g" ${dcrOutput} + + if [ "${istioEnabled}" == "true" ]; then + exposeAdminNodePortPrefix="${disabledPrefix}" + fi + + sed -i -e "s:%EXPOSE_T3_CHANNEL_PREFIX%:${exposeAdminT3ChannelPrefix}:g" ${dcrOutput} + sed -i -e "s:%EXPOSE_ANY_CHANNEL_PREFIX%:${exposeAnyChannelPrefix}:g" ${dcrOutput} + sed -i -e "s:%EXPOSE_ADMIN_PORT_PREFIX%:${exposeAdminNodePortPrefix}:g" ${dcrOutput} + sed -i -e "s:%ADMIN_NODE_PORT%:${adminNodePort}:g" ${dcrOutput} + sed -i -e "s:%CLUSTER_NAME%:${clusterName}:g" ${dcrOutput} + sed -i -e "s:%INITIAL_MANAGED_SERVER_REPLICAS%:${initialManagedServerReplicas}:g" ${dcrOutput} + sed -i -e "s:%ISTIO_PREFIX%:${istioPrefix}:g" ${dcrOutput} + sed -i -e "s:%ISTIO_ENABLED%:${istioEnabled}:g" ${dcrOutput} + sed -i -e "s:%ISTIO_READINESS_PORT%:${istioReadinessPort}:g" ${dcrOutput} + # MII settings are used for model-in-image integration testing + sed -i -e "s:%MII_PREFIX%:${miiPrefix}:g" ${dcrOutput} + sed -i -e "s:%MII_CONFIG_MAP_PREFIX%:${miiConfigMapPrefix}:g" ${dcrOutput} + sed -i -e "s:%MII_CONFIG_MAP%:${miiConfigMap}:g" ${dcrOutput} + sed -i -e "s:%WDT_DOMAIN_TYPE%:${wdtDomainType}:g" ${dcrOutput} + + buildServerPodResources + if [ -z "${serverPodResources}" ]; then + sed -i -e "/%OPTIONAL_SERVERPOD_RESOURCES%/d" ${dcrOutput} + else + if [[ $(uname) -eq "Darwin" ]]; then + serverPodResources=$(echo "${serverPodResources}" | sed -e 's/\\n/%NEWLINE%/g') + sed -i -e "s:%OPTIONAL_SERVERPOD_RESOURCES%:${serverPodResources}:g" ${dcrOutput} + sed -i -e $'s|%NEWLINE%|\\\n|g' ${dcrOutput} + else + sed -i -e "s:%OPTIONAL_SERVERPOD_RESOURCES%:${serverPodResources}:g" ${dcrOutput} + fi + fi + + if [ "${domainHomeInImage}" == "true" ]; then + + # now we know which image to use, update the domain yaml file + if [ -z $image ]; then + sed -i -e "s|%WEBLOGIC_IMAGE%|${defaultImageName}|g" ${dcrOutput} + else + sed -i -e "s|%WEBLOGIC_IMAGE%|${image}|g" ${dcrOutput} + fi + else + sed -i -e "s:%WEBLOGIC_IMAGE%:${image}:g" ${dcrOutput} + fi + fi + + # Remove any "...yaml-e" and "...properties-e" files left over from running sed + rm -f ${domainOutputDir}/*.yaml-e + rm -f ${domainOutputDir}/*.properties-e + +} + + +# +# Function to markup the wdt model file +# +function updateModelFile { + # Update the wdt model file with kubernetes section + modelFile="${domainOutputDir}/tmp/wdt_model.yaml" + cat ${scriptDir}/wdt_k8s_model_template.yaml >> ${modelFile} + + sed -i -e "s:%DOMAIN_UID%:${domainUID}:g" ${modelFile} + sed -i -e "s:%NAMESPACE%:$namespace:g" ${modelFile} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${modelFile} + sed -i -e "s:%DOMAIN_HOME_SOURCE_TYPE%:${domainHomeSourceType}:g" ${modelFile} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_POLICY%:${imagePullPolicy}:g" ${modelFile} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%:${imagePullSecretPrefix}:g" ${modelFile} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_NAME%:${imagePullSecretName}:g" ${modelFile} + sed -i -e "s:%WEBLOGIC_CREDENTIALS_SECRET_NAME%:${weblogicCredentialsSecretName}:g" ${modelFile} + sed -i -e "s:%INCLUDE_SERVER_OUT_IN_POD_LOG%:${includeServerOutInPodLog}:g" ${modelFile} + sed -i -e "s:%LOG_HOME_ON_PV_PREFIX%:${logHomeOnPVPrefix}:g" ${modelFile} + sed -i -e "s:%LOG_HOME_ENABLED%:${logHomeOnPV}:g" ${modelFile} + sed -i -e "s:%LOG_HOME%:${logHome}:g" ${modelFile} + sed -i -e "s:%HTTP_ACCESS_LOG_IN_LOG_HOME%:${httpAccessLogInLogHome}:g" ${modelFile} + sed -i -e "s:%DATA_HOME%:${dataHome}:g" ${modelFile} + sed -i -e "s:%SERVER_START_POLICY%:${serverStartPolicy}:g" ${modelFile} + sed -i -e "s;%JAVA_OPTIONS%;${javaOptions};g" ${modelFile} + sed -i -e "s:%DOMAIN_PVC_NAME%:${persistentVolumeClaimName}:g" ${modelFile} + sed -i -e "s:%DOMAIN_ROOT_DIR%:${domainPVMountPath}:g" ${modelFile} + + if [ "${istioEnabled}" == "true" ]; then + exposeAdminNodePortPrefix="${disabledPrefix}" + fi + + sed -i -e "s:%EXPOSE_T3_CHANNEL_PREFIX%:${exposeAdminT3ChannelPrefix}:g" ${modelFile} + sed -i -e "s:%EXPOSE_ANY_CHANNEL_PREFIX%:${exposeAnyChannelPrefix}:g" ${modelFile} + sed -i -e "s:%EXPOSE_ADMIN_PORT_PREFIX%:${exposeAdminNodePortPrefix}:g" ${modelFile} + sed -i -e "s:%ADMIN_NODE_PORT%:${adminNodePort}:g" ${modelFile} + sed -i -e "s:%CLUSTER_NAME%:${clusterName}:g" ${modelFile} + sed -i -e "s:%INITIAL_MANAGED_SERVER_REPLICAS%:${initialManagedServerReplicas}:g" ${modelFile} + sed -i -e "s:%ISTIO_PREFIX%:${istioPrefix}:g" ${modelFile} + sed -i -e "s:%ISTIO_ENABLED%:${istioEnabled}:g" ${modelFile} + sed -i -e "s:%ISTIO_READINESS_PORT%:${istioReadinessPort}:g" ${modelFile} + # MII settings are used for model-in-image integration testing + sed -i -e "s:%MII_PREFIX%:${miiPrefix}:g" ${modelFile} + sed -i -e "s:%MII_CONFIG_MAP_PREFIX%:${miiConfigMapPrefix}:g" ${modelFile} + sed -i -e "s:%MII_CONFIG_MAP%:${miiConfigMap}:g" ${modelFile} + sed -i -e "s:%WDT_DOMAIN_TYPE%:${wdtDomainType}:g" ${modelFile} + + buildServerPodResources + if [ -z "${serverPodResources}" ]; then + sed -i -e "/%OPTIONAL_SERVERPOD_RESOURCES%/d" ${modelFile} + else + if [[ $(uname) -eq "Darwin" ]]; then + serverPodResources=$(echo "${serverPodResources}" | sed -e 's/\\n/%NEWLINE%/g') + sed -i -e "s:%OPTIONAL_SERVERPOD_RESOURCES%:${serverPodResources}:g" ${modelFile} + sed -i -e $'s|%NEWLINE%|\\\n|g' ${modelFile} + else + sed -i -e "s:%OPTIONAL_SERVERPOD_RESOURCES%:${serverPodResources}:g" ${modelFile} + fi + fi + + sed -i -e "s:%WEBLOGIC_IMAGE%:${image}:g" ${modelFile} +} + +# +# Function to create the domain recource +# +function createDomainResource { + kubectl apply -f ${dcrOutput} + + attempts=0 + while [ "$DCR_AVAIL" != "1" ] && [ ! $attempts -eq 10 ]; do + attempts=$((attempts + 1)) + sleep 1 + DCR_AVAIL=`kubectl get domain ${domainUID} -n ${namespace} | grep ${domainUID} | wc | awk ' { print $1; } '` + done + if [ "${DCR_AVAIL}" != "1" ]; then + fail "The domain resource ${domainUID} was not found" + fi +} + +# +# Function to create a domain +# $1 - boolean value indicating the location of the domain home +# true means domain home in image +# false means domain home on PV +# +function createDomain { + if [ "$#" != 1 ]; then + fail "The function must be called with domainHomeInImage parameter." + fi + + domainHomeInImage="${1}" + if [ "true" != "${domainHomeInImage}" ] && [ "false" != "${domainHomeInImage}" ]; then + fail "The value of domainHomeInImage must be true or false: ${domainHomeInImage}" + fi + + # Setup the environment for running this script and perform initial validation checks + initialize + + # Generate files for creating the domain + createFiles + + # Check that the domain secret exists and contains the required elements + validateDomainSecret + + # Validate the domain's persistent volume claim + if [ "${doValidation}" == true ] && [ "${domainHomeInImage}" == false -o "${logHomeOnPV}" == true ]; then + validateDomainPVC + fi + + # Create the WebLogic domain home + createDomainHome + + if [ "${executeIt}" = true ]; then + createDomainResource + fi + + # Print a summary + printSummary +} + +# +# Function to update a domain +# $1 - boolean value indicating the location of the domain home +# true means domain home in image +# false means domain home on PV +# +function updateDomain { + + domainHomeInImage="false" + + # Setup the environment for running this script and perform initial validation checks + initialize + + # Generate files for creating the domain + createFiles update + + # Check that the domain secret exists and contains the required elements + validateDomainSecret + + # Validate the domain's persistent volume claim + if [ "${doValidation}" == true ]; then + validateDomainPVC + fi + + # Create the WebLogic domain home + updateDomainHome + + if [ "${executeIt}" = true ]; then + createDomainResource + fi + + # Print a summary + printSummary +} + +# checks if a given pod in a NameSpace has been deleted +function checkPodDelete(){ + + pod=$1 + ns=$2 + status="Terminating" + + if [ -z ${1} ]; then + echo "No Pod name provided " + exit -1 + fi + + if [ -z ${2} ]; then + echo "No NameSpace provided " + exit -2 + fi + + echo "Checking Status for Pod [$pod] in namespace [${ns}]" + max=10 + count=1 + while [ $count -le $max ] ; do + sleep 5 + pod=`kubectl get po/$1 -n ${ns} | grep -v NAME | awk '{print $1}'` + if [ -z ${pod} ]; then + status="Terminated" + echo "Pod [$1] removed from nameSpace [${ns}]" + break; + fi + count=`expr $count + 1` + echo "Pod [$pod] Status [${status}]" + done + + if [ $count -gt $max ] ; then + echo "[ERROR] The Pod[$1] in NameSpace [$ns] could not be deleted in 50s"; + exit 1 + fi +} + +# Checks if all container(s) in a pod are running state based on READY column +#NAME READY STATUS RESTARTS AGE +#domain1-adminserver 1/1 Running 0 4m + +function checkPodState(){ + + status="NotReady" + max=60 + count=1 + + pod=$1 + ns=$2 + state=${3:-1/1} + + echo "Checking Pod READY column for State [$state]" + pname=`kubectl get po -n ${ns} | grep -w ${pod} | awk '{print $1}'` + if [ -z ${pname} ]; then + echo "No such pod [$pod] exists in NameSpace [$ns] " + exit -1 + fi + + rcode=`kubectl get po ${pname} -n ${ns} | grep -w ${pod} | awk '{print $2}'` + [[ ${rcode} -eq "${state}" ]] && status="Ready" + + while [ ${status} != "Ready" -a $count -le $max ] ; do + sleep 5 + rcode=`kubectl get po/$pod -n ${ns} | grep -v NAME | awk '{print $2}'` + [[ ${rcode} -eq "1/1" ]] && status="Ready" + echo "Pod [$1] Status is ${status} Iter [$count/$max]" + count=`expr $count + 1` + done + if [ $count -gt $max ] ; then + echo "[ERROR] Unable to start the Pod [$pod] after 300s "; + exit 1 + fi + + pname=`kubectl get po -n ${ns} | grep -w ${pod} | awk '{print $1}'` + kubectl -n ${ns} get po ${pname} +} + +# Checks if a pod is available in a given namespace +function checkPod(){ + + max=20 + count=1 + + pod=$1 + ns=$2 + + pname=`kubectl get po -n ${ns} | grep -w ${pod} | awk '{print $1}'` + if [ -z ${pname} ]; then + echo "No such pod [$pod] exists in NameSpace [$ns]" + sleep 10 + fi + + rcode=`kubectl get po -n ${ns} | grep -w ${pod} | awk '{print $1}'` + if [ ! -z ${rcode} ]; then + echo "[$pod] already initialized .. " + return 0 + fi + + echo "The POD [${pod}] has not been initialized ..." + while [ -z ${rcode} ]; do + [[ $count -gt $max ]] && break + echo "Pod[$pod] is being initialized ..." + sleep 5 + rcode=`kubectl get po -n ${ns} | grep $pod | awk '{print $1}'` + count=`expr $count + 1` + done + + if [ $count -gt $max ] ; then + echo "[ERROR] Could not find Pod [$pod] after 120s"; + exit 1 + fi +} + +# Checks if a service is available in a given namespace +function checkService(){ + svc=$1 + ns=$2 + startSecs=$SECONDS + maxWaitSecs=20 + while [ -z "`kubectl get service -n ${ns} | grep -w ${svc}`" ]; do + if [ $((SECONDS - startSecs)) -lt $maxWaitSecs ]; then + echo "Service [$svc] not found after $((SECONDS - startSecs)) seconds, retrying ..." + sleep 5 + else + echo "[Error] Could not find Service [$svc] after $((SECONDS - startSecs)) seconds" + exit 1 + fi + done + echo "Service [$svc] found" +} diff --git a/OracleWebCenterPortal/kubernetes/common/validate.sh b/OracleWebCenterPortal/kubernetes/common/validate.sh new file mode 100644 index 000000000..1a407a99a --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/common/validate.sh @@ -0,0 +1,481 @@ +#!/usr/bin/env bash +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description +# Common validation functions shared by all other scripts that process inputs properties. +# + +# +# Function to note that a validate error has occurred +# +function validationError { + printError $* + validateErrors=true +} + +# +# Function to cause the script to fail if there were any validation errors +# +function failIfValidationErrors { + if [ "$validateErrors" = true ]; then + fail 'The errors listed above must be resolved before the script can continue' + fi +} + +# +# Function to validate that a list of required input parameters were specified +# +function validateInputParamsSpecified { + for p in $*; do + local name=$p + local val=${!name} + if [ -z "$val" ]; then + validationError "The ${name} parameter in ${valuesInputFile} is missing, null or empty" + fi + done +} + +# +# Function to validate that a list of input parameters have boolean values. +# It assumes that validateInputParamsSpecified will also be called for these params. +# +function validateBooleanInputParamsSpecified { + validateInputParamsSpecified $* + for p in $*; do + local name=$p + local val=${!name} + if ! [ -z $val ]; then + if [ "true" != "$val" ] && [ "false" != "$val" ]; then + validationError "The value of $name must be true or false: $val" + fi + fi + done +} + +# +# Function to validate that a list of input parameters have integer values. +# +function validateIntegerInputParamsSpecified { + validateInputParamsSpecified $* + for p in $*; do + local name=$p + local val=${!name} + if ! [ -z $val ]; then + local intVal="" + printf -v intVal '%d' "$val" 2>/dev/null + if ! [ "${val}" == "${intVal}" ]; then + validationError "The value of $name must be an integer: $val" + fi + fi + done +} + +# +# Function to check if a value is lowercase +# $1 - name of object being checked +# $2 - value to check +function validateLowerCase { + local lcVal=$(toLower $2) + if [ "$lcVal" != "$2" ]; then + validationError "The value of $1 must be lowercase: $2" + fi +} + +# +# Function to check if a value is lowercase and legal DNS name +# $1 - name of object being checked +# $2 - value to check +function validateDNS1123LegalName { + local val=$(toDNS1123Legal $2) + if [ "$val" != "$2" ]; then + validationError "The value of $1 contains invalid charaters: $2" + fi +} + +# +# Function to validate the namespace +# +function validateNamespace { + validateLowerCase "namespace" ${namespace} +} + +# +# Function to validate the version of the inputs file +# +function validateVersion { + local requiredVersion=${requiredInputsVersion} + if [ "${version}" != "${requiredVersion}" ]; then + validationError "Invalid version: \"${version}\". Must be ${requiredVersion}." + fi +} + +# +# Function to ensure the domain uid is a legal DNS name +# +function validateDomainUid { + validateLowerCase "domainUID" ${domainUID} + validateDNS1123LegalName domainUID ${domainUID} +} + +# +# Function to ensure the namespace is lowercase +# +function validateNamespace { + validateLowerCase "namespace" ${namespace} +} + +# +# Create an instance of clusterName to be used in cases where a legal DNS name is required. +# +function validateClusterName { + clusterNameSVC=$(toDNS1123Legal $clusterName) +} + +# +# Create an instance of adminServerName to be used in cases where a legal DNS name is required. +# +function validateAdminServerName { + adminServerNameSVC=$(toDNS1123Legal $adminServerName) +} + +# +# Create an instance of adminServerName to be used in cases where a legal DNS name is required. +# +function validateManagedServerNameBase { + managedServerNameBaseSVC=$(toDNS1123Legal $managedServerNameBase) +} + +# +# Function to validate the secret name +# +function validateWeblogicCredentialsSecretName { + validateLowerCase "weblogicCredentialsSecretName" ${weblogicCredentialsSecretName} +} + +# +# Function to validate the weblogic image pull policy +# +function validateWeblogicImagePullPolicy { + if [ ! -z ${imagePullPolicy} ]; then + case ${imagePullPolicy} in + "IfNotPresent") + ;; + "Always") + ;; + "Never") + ;; + *) + validationError "Invalid value for imagePullPolicy: ${imagePullPolicy}. Valid values are IfNotPresent, Always, and Never." + ;; + esac + else + # Set the default + imagePullPolicy="IfNotPresent" + fi + failIfValidationErrors +} + +# +# Function to validate the fmwDomainType +# +function validateFmwDomainType { + if [ ! -z ${fmwDomainType} ]; then + case ${fmwDomainType} in + "JRF") + ;; + "RestrictedJRF") + ;; + *) + validationError "Invalid value for fmwDomainType: ${fmwDomainType}. Valid values are JRF or restrictedJRF." + ;; + esac + else + # Set the default + fmwDomainType="JRF" + fi + failIfValidationErrors +} + +# +# Function to validate the weblogic image pull secret name +# +function validateWeblogicImagePullSecretName { + if [ ! -z ${imagePullSecretName} ]; then + validateLowerCase imagePullSecretName ${imagePullSecretName} + imagePullSecretPrefix="" + if [ "${generateOnly}" = false ]; then + validateWeblogicImagePullSecret + fi + else + # Set name blank when not specified, and comment out the yaml + imagePullSecretName="" + imagePullSecretPrefix="#" + fi +} + +# +# Function to validate the weblogic image pull secret exists +# +function validateWeblogicImagePullSecret { + # The kubernetes secret for pulling images from a container registry is optional. + # If it was specified, make sure it exists. + validateSecretExists ${imagePullSecretName} ${namespace} + failIfValidationErrors +} + +# try to execute kubectl to see whether kubectl is available +function validateKubectlAvailable { + if ! [ -x "$(command -v kubectl)" ]; then + validationError "kubectl is not installed" + fi +} + +# Function to validate the server start policy value +# +function validateServerStartPolicy { + validateInputParamsSpecified serverStartPolicy + if [ ! -z "${serverStartPolicy}" ]; then + case ${serverStartPolicy} in + "NEVER") + ;; + "ALWAYS") + ;; + "IF_NEEDED") + ;; + "ADMIN_ONLY") + ;; + *) + validationError "Invalid value for serverStartPolicy: ${serverStartPolicy}. Valid values are 'NEVER', 'ALWAYS', 'IF_NEEDED', and 'ADMIN_ONLY'." + ;; + esac + fi +} + +# +# Function to validate the weblogic domain storage reclaim policy +# +function validateWeblogicDomainStorageReclaimPolicy { + validateInputParamsSpecified weblogicDomainStorageReclaimPolicy + if [ ! -z "${weblogicDomainStorageReclaimPolicy}" ]; then + case ${weblogicDomainStorageReclaimPolicy} in + "Retain") + ;; + "Delete") + if [ "${weblogicDomainStoragePath:0:5}" != "/tmp/" ]; then + validationError "ERROR - Invalid value for weblogicDomainStorageReclaimPolicy ${weblogicDomainStorageReclaimPolicy} with weblogicDomainStoragePath ${weblogicDomainStoragePath} that is not /tmp/" + fi + ;; + "Recycle") + ;; + *) + validationError "Invalid value for weblogicDomainStorageReclaimPolicy: ${weblogicDomainStorageReclaimPolicy}. Valid values are Retain, Delete and Recycle." + ;; + esac + fi +} + +# +# Function to validate the weblogic domain storage type +# +function validateWeblogicDomainStorageType { + validateInputParamsSpecified weblogicDomainStorageType + if [ ! -z "${weblogicDomainStorageType}" ]; then + case ${weblogicDomainStorageType} in + "HOST_PATH") + ;; + "NFS") + validateInputParamsSpecified weblogicDomainStorageNFSServer + ;; + *) + validationError "Invalid value for weblogicDomainStorageType: ${weblogicDomainStorageType}. Valid values are HOST_PATH and NFS." + ;; + esac + fi +} + +# +# Function to validate the load balancer value +# +function validateLoadBalancer { + validateInputParamsSpecified loadBalancer + if [ ! -z "${loadBalancer}" ]; then + case ${loadBalancer} in + "TRAEFIK") + ;; + "APACHE") + ;; + "VOYAGER") + ;; + "NONE") + ;; + *) + validationError "Invalid value for loadBalancer: ${loadBalancer}. Valid values are APACHE, TRAEFIK, VOYAGER and NONE." + ;; + esac + fi +} + +# +# Function to validate a kubernetes secret exists +# $1 - the name of the secret +# $2 - namespace +function validateSecretExists { + echo "Checking to see if the secret ${1} exists in namespace ${2}" + local SECRET=`kubectl get secret ${1} -n ${2} | grep ${1} | wc | awk ' { print $1; }'` + if [ "${SECRET}" != "1" ]; then + validationError "The secret ${1} was not found in namespace ${2}" + fi +} + +# +# Function to validate the domain secret +# +function validateDomainSecret { + # Verify the secret exists + validateSecretExists ${weblogicCredentialsSecretName} ${namespace} + failIfValidationErrors + + # Verify the secret contains a username + SECRET=`kubectl get secret ${weblogicCredentialsSecretName} -n ${namespace} -o jsonpath='{.data}' | tr -d '"' | grep username: | wc | awk ' { print $1; }'` + if [ "${SECRET}" != "1" ]; then + validationError "The domain secret ${weblogicCredentialsSecretName} in namespace ${namespace} does contain a username" + fi + + # Verify the secret contains a password + SECRET=`kubectl get secret ${weblogicCredentialsSecretName} -n ${namespace} -o jsonpath='{.data}' | tr -d '"'| grep password: | wc | awk ' { print $1; }'` + if [ "${SECRET}" != "1" ]; then + validationError "The domain secret ${weblogicCredentialsSecretName} in namespace ${namespace} does contain a password" + fi + failIfValidationErrors +} + +# +# function to validate if we will be using wdt or wlst to create the domain +# +function validateDomainFilesDir { + useWdt=true + if [ -z "${createDomainFilesDir}" ] || [ "${createDomainFilesDir}" == "wlst" ]; then + useWdt=false + fi +} + +# +# Function to validate the common input parameters +# +function validateCommonInputs { + sample_name=${1:-"other"} + + # Parse the common inputs file + parseCommonInputs + + validateInputParamsSpecified \ + adminServerName \ + domainUID \ + clusterName \ + managedServerNameBase \ + namespace \ + includeServerOutInPodLog \ + version + + validateIntegerInputParamsSpecified \ + adminPort \ + initialManagedServerReplicas \ + managedServerPort \ + t3ChannelPort \ + adminNodePort + + if [ ! "${sample_name}" == "fmw-domain-home-in-image" ]; then + validateIntegerInputParamsSpecified configuredManagedServerCount + fi + + validateBooleanInputParamsSpecified \ + productionModeEnabled \ + exposeAdminT3Channel \ + exposeAdminNodePort \ + includeServerOutInPodLog + + export requiredInputsVersion="create-weblogic-sample-domain-inputs-v1" + validateVersion + + validateDomainUid + validateNamespace + validateAdminServerName + validateManagedServerNameBase + validateClusterName + validateWeblogicCredentialsSecretName + validateServerStartPolicy + validateWeblogicImagePullPolicy + validateWeblogicImagePullSecretName + validateFmwDomainType + validateDomainFilesDir + # Below three validate methods are used for MII integration testing + validateWdtDomainType + validateWdtModelFile + validateWdtModelPropertiesFile + + failIfValidationErrors +} + +# +# Function to validate the domain's persistent volume claim has been created +# +function validateDomainPVC { + # Check if the persistent volume claim is already available + checkPvcExists ${persistentVolumeClaimName} ${namespace} + if [ "${PVC_EXISTS}" = "false" ]; then + validationError "The domain persistent volume claim ${persistentVolumeClaimName} does not exist in namespace ${namespace}" + fi + failIfValidationErrors +} + +# +# Function to validate the WDT model file exists +# used for MII integration testing +# +function validateWdtModelFile { + # Check if the model file exists + if [ ! -z $wdtModelFile ]; then + if [ ! -f $wdtModelFile ]; then + validationError "The WDT model file ${wdtModelFile} does not exist" + fi + fi + failIfValidationErrors +} + +# +# Function to validate the WDT model property file exists +# used for MII integration testing +# +function validateWdtModelPropertiesFile { + # Check if the model property file exists + if [ ! -z $wdtModelPropertiesFile ]; then + if [ ! -f $wdtModelPropertiesFile ]; then + validationError "The WDT model property file ${wdtModelPropertiesFile} does not exist" + fi + fi + failIfValidationErrors +} + +# Function to validate the wdtDomainType +# used for MII integration testing +function validateWdtDomainType { + if [ ! -z ${wdtDomainType} ]; then + case ${wdtDomainType} in + "WLS") + ;; + "JRF") + ;; + "RestrictedJRF") + ;; + *) + validationError "Invalid value for wdtDomainType: ${wdtDomainType}. Valid values are WLS or JRF or restrictedJRF." + ;; + esac + else + # Set the default + wdtDomainType="WLS" + fi + failIfValidationErrors +} + diff --git a/OracleWebCenterPortal/kubernetes/common/wdt-and-wit-utility.sh b/OracleWebCenterPortal/kubernetes/common/wdt-and-wit-utility.sh new file mode 100644 index 000000000..aa9cc691c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/common/wdt-and-wit-utility.sh @@ -0,0 +1,439 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description: +# +# This script contains functions for installing WebLogic Deploy Tool (WDT) and +# WebLogic Image Tool (WIT), and for running WDT. +# +# +# Usage: +# +# Export customized values for the input shell environment variables as needed +# before calling this script. +# +# Outputs: +# +# WDT install: WDT_DIR/weblogic-deploy/... +# +# Copy of wdt model: WDT_DIR/$(basename WDT_MODEL_FILE) +# Copy of wdt vars: WDT_DIR/$(basename WDT_VAR_FILE) +# +# WDT logs: WDT_DIR/weblogic-deploy/logs/... +# WDT stdout: WDT_DIR/createDomain.sh.out +# +# WebLogic domain home: DOMAIN_HOME_DIR +# default: /shared/domains/ +# +# Input environment variables: +# +# ORACLE_HOME Oracle home with a WebLogic install. +# default: /u01/oracle +# +# DOMAIN_HOME_DIR Target location for generated domain. +# +# WDT_MODEL_FILE Full path to WDT model file. +# default: the directory that contains this script +# plus "/wdt_model.yaml" +# +# WDT_VAR_FILE Full path to WDT variable file (java properties format). +# default: the directory that contains this script +# plus "/create-domain-inputs.yaml" +# +# WDT_DIR Target location to install and run WDT, and to keep a copy of +# $WDT_MODEL_FILE and $WDT_MODEL_VARS. Also the location +# of WDT log files. +# default: /shared/wdt +# +# WDT_VERSION WDT version to download. +# default: LATEST +# +# WDT_INSTALL_ZIP_FILE Filename of WDT install zip. +# default: weblogic-deploy.zip +# +# WDT_INSTALL_ZIP_URL URL for downloading WDT install zip +# default: https://github.com/oracle/weblogic-deploy-tooling/releases/latest/download/$WDT_INSTALL_ZIP_FILE +# +# WIT_DIR Target location to install WIT +# default: /shared/imagetool +# +# WIT_VERSION WIT version to download. +# default: LATEST +# +# WIT_INSTALL_ZIP_FILE Filename of WIT install zip. +# default: imagetool.zip +# +# WIT_INSTALL_ZIP_URL URL for downloading WIT install zip +# default: https://github.com/oracle/weblogic-image-tool/releases/latest/download/$WIT_INSTALL_ZIP_FILE +# + + +# Initialize globals + +export ORACLE_HOME=${ORACLE_HOME:-/u01/oracle} + +SCRIPTPATH="$( cd "$(dirname "$0")" > /dev/null 2>&1 ; pwd -P )" +WDT_MODEL_FILE=${WDT_MODEL_FILE:-"$SCRIPTPATH/wdt_model.yaml"} +WDT_VAR_FILE=${WDT_VAR_FILE:-"$SCRIPTPATH/create-domain-inputs.yaml"} + +WDT_DIR=${WDT_DIR:-/shared/wdt} +WDT_VERSION=${WDT_VERSION:-LATEST} + +WIT_DIR=${WIT_DIR:-/shared/imagetool} +WIT_VERSION=${WIT_VERSION:-LATEST} + +DOMAIN_TYPE="${DOMAIN_TYPE:-WLS}" + +function download { + local fileUrl="${1}" + + local curl_res=1 + max=20 + count=0 + while [ $curl_res -ne 0 -a $count -lt $max ] ; do + sleep 1 + count=`expr $count + 1` + for proxy in "${https_proxy}" "${https_proxy2}"; do + echo @@ "Info: Downloading $fileUrl with https_proxy=\"$proxy\"" + https_proxy="${proxy}" \ + curl --silent --show-error --connect-timeout 10 -O -L $fileUrl + curl_res=$? + [ $curl_res -eq 0 ] && break + done + done + if [ $curl_res -ne 0 ]; then + echo @@ "Error: Download failed." + return 1 + fi +} + +function run_wdt { + # + # Run WDT using WDT_VAR_FILE, WDT_MODEL_FILE, and ORACLE_HOME. + # Output: + # - result domain will be in DOMAIN_HOME_DIR + # - logging output is in $WDT_DIR/createDomain.sh.out and $WDT_DIR/weblogic-deploy/logs + # - WDT_VAR_FILE & WDT_MODEL_FILE will be copied to WDT_DIR. + # + + local action="${1}" + + # Input files and directories. + + local inputs_orig="$WDT_VAR_FILE" + local model_orig="$WDT_MODEL_FILE" + local oracle_home="$ORACLE_HOME" + local domain_type="$DOMAIN_TYPE" + local wdt_bin_dir="$WDT_DIR/weblogic-deploy/bin" + local wdt_createDomain_script="$wdt_bin_dir/createDomain.sh" + + if [ ${action} = "create" ]; then + local wdt_domain_script="$wdt_bin_dir/createDomain.sh" + else + local wdt_domain_script="$wdt_bin_dir/updateDomain.sh" + fi + + local domain_home_dir="$DOMAIN_HOME_DIR" + if [ -z "${domain_home_dir}" ]; then + local domain_dir="/shared/domains" + local domain_uid=`egrep 'domainUID' $inputs_orig | awk '{print $2}'` + local domain_home_dir=$domain_dir/$domain_uid + fi + + mkdir -p $domain_home_dir + + # Output files and directories. + + local inputs_final=$WDT_DIR/$(basename "$inputs_orig") + local model_final=$WDT_DIR/$(basename "$model_orig") + if [ ${action} = "create" ]; then + local out_file=$WDT_DIR/createDomain.sh.out + else + local out_file=$WDT_DIR/updateDomain.sh.out + fi + local wdt_log_dir="$WDT_DIR/weblogic-deploy/logs" + + echo @@ "Info: About to run WDT ${wdt_domain_script}" + + for directory in wdt_bin_dir SCRIPTPATH WDT_DIR oracle_home; do + if [ ! -d "${!directory}" ]; then + echo @@ "Error: Could not find ${directory} directory ${!directory}." + return 1 + fi + done + + for fil in inputs_orig model_orig wdt_createDomain_script; do + if [ ! -f "${!fil}" ]; then + echo @@ "Error: Could not find ${fil} file ${!fil}." + return 1 + fi + done + + cp $model_orig $model_final || return 1 + cp $inputs_orig $inputs_final || return 1 + + local save_dir=`pwd` + cd $WDT_DIR || return 1 + + cmd=" + $wdt_domain_script + -oracle_home $oracle_home + -domain_type $domain_type + -domain_home $domain_home_dir + -model_file $model_final + -variable_file $inputs_final + " + + echo @@ "Info: About to run the following WDT command:" + echo "${cmd}" + echo @@ "Info: WDT output will be in $out_file and $wdt_log_dir" + eval $cmd > $out_file 2>&1 + local wdt_res=$? + + cd $save_dir + + if [ $wdt_res -ne 0 ]; then + if [ ${action} = "create" ]; then + cat $WDT_DIR/createDomain.sh.out + echo @@ "Info: WDT createDomain.sh output is in $out_file and $wdt_log_dir" + echo @@ "Error: WDT createDomain.sh failed." + return 1 + else + cat $WDT_DIR/updateDomain.sh.out + echo @@ "Info: WDT updateDomain.sh output is in $out_file and $wdt_log_dir" + echo @@ "Error: WDT updateDomain.sh failed." + return 1 + fi + fi + + cd $WDT_DIR || return 1 + + cmd=" + $wdt_bin_dir/extractDomainResource.sh + -oracle_home $oracle_home + -domain_resource_file domain${action}.yaml + -domain_home $domain_home_dir + -model_file $model_final + -variable_file $inputs_final + " + echo @@ "Info: About to run the following WDT command:" + echo "${cmd}" + echo @@ "Info: WDT output will be in extract${action}.out and $wdt_log_dir" + eval $cmd > extract${action}.out 2>&1 + local wdt_res=$? + + cd $save_dir + + if [ $wdt_res -ne 0 ]; then + cat $WDT_DIR/extract${action}.out + echo @@ "Info: WDT extractDomainResource output is in extract${action}.out and $wdt_log_dir" + echo @@ "Error: WDT createDomain.sh failed." + return 1 + fi + + if [ ${action} = "create" ]; then + # chmod -R g+w $domain_home_dir || return 1 + echo @@ "Info: WDT createDomain.sh succeeded." + else + echo @@ "Info: WDT updateDomain.sh succeeded." + fi + + return 0 +} + +function setup_wdt_shared_dir { + mkdir -p $WDT_DIR || return 1 +} + +# +# Install Weblogic Server Deploy Tooling to ${WDT_DIR} +# +function install_wdt { + + WDT_INSTALL_ZIP_FILE="${WDT_INSTALL_ZIP_FILE:-weblogic-deploy.zip}" + + if [ "$WDT_VERSION" == "LATEST" ]; then + WDT_INSTALL_ZIP_URL=${WDT_INSTALL_ZIP_URL:-"https://github.com/oracle/weblogic-deploy-tooling/releases/latest/download/$WDT_INSTALL_ZIP_FILE"} + else + WDT_INSTALL_ZIP_URL=${WDT_INSTALL_ZIP_URL:-"https://github.com/oracle/weblogic-deploy-tooling/releases/download/release-$WDT_VERSION/$WDT_INSTALL_ZIP_FILE"} + fi + + local save_dir=`pwd` + cd $WDT_DIR || return 1 + + echo @@ "Info: Downloading $WDT_INSTALL_ZIP_URL " + download $WDT_INSTALL_ZIP_URL || return 1 + + if [ ! -f $WDT_INSTALL_ZIP_FILE ]; then + cd $save_dir + echo @@ "Error: Download failed or $WDT_INSTALL_ZIP_FILE not found." + return 1 + fi + + echo @@ "Info: Archive downloaded to $WDT_DIR/$WDT_INSTALL_ZIP_FILE, about to unzip via 'jar xf'." + + jar xf $WDT_INSTALL_ZIP_FILE + local jar_res=$? + + cd $save_dir + + if [ $jar_res -ne 0 ]; then + echo @@ "Error: Install failed while unzipping $WDT_DIR/$WDT_INSTALL_ZIP_FILE" + return $jar_res + fi + + if [ ! -d "$WDT_DIR/weblogic-deploy/bin" ]; then + echo @@ "Error: Install failed: directory '$WDT_DIR/weblogic-deploy/bin' not found." + return 1 + fi + + chmod 775 $WDT_DIR/weblogic-deploy/bin/* || return 1 + + echo @@ "Info: Install succeeded, wdt install is in the $WDT_DIR/weblogic-deploy directory." + return 0 +} + +# +# Install WebLogic Image Tool to ${WIT_DIR}. Used by install_wit_if_needed. +# Do not call this function directory. +# +function install_wit { + + WIT_INSTALL_ZIP_FILE="${WIT_INSTALL_ZIP_FILE:-imagetool.zip}" + + if [ "$WIT_VERSION" == "LATEST" ]; then + WIT_INSTALL_ZIP_URL=${WDT_INSTALL_ZIP_URL:-"https://github.com/oracle/weblogic-image-tool/releases/latest/download/$WIT_INSTALL_ZIP_FILE"} + else + WIT_INSTALL_ZIP_URL=${WIT_INSTALL_ZIP_URL:-"https://github.com/oracle/weblogic-image-tool/releases/download/release-$WIT_VERSION/$WIT_INSTALL_ZIP_FILE"} + fi + + + + local save_dir=`pwd` + + echo @@ "imagetool.sh not found in ${imagetoolBinDir}. Installing imagetool..." + + echo @@ "Info: Downloading $WIT_INSTALL_ZIP_URL " + download $WIT_INSTALL_ZIP_URL || return 1 + + if [ ! -f $WIT_INSTALL_ZIP_FILE ]; then + cd $save_dir + echo @@ "Error: Download failed or $WIT_INSTALL_ZIP_FILE not found." + return 1 + fi + echo @@ "Info: Archive downloaded to $WIT_DIR/$WIT_INSTALL_ZIP_FILE, about to unzip via 'jar xf'." + + jar xf $WIT_INSTALL_ZIP_FILE + local jar_res=$? + + cd $save_dir + + if [ $jar_res -ne 0 ]; then + echo @@ "Error: Install failed while unzipping $WIT_DIR/$WIT_INSTALL_ZIP_FILE" + return $jar_res + fi + + if [ ! -d "$WIT_DIR/imagetool/bin" ]; then + echo @@ "Error: Install failed: directory '$WIT_DIR/imagetool/bin' not found." + return 1 + fi + + chmod 775 $WIT_DIR/imagetool/bin/* || return 1 +} + +# +# Checks whether WebLogic Image Tool is already installed under ${WIT_DIR}, and install +# it if not. +# +function install_wit_if_needed { + + local save_dir=`pwd` + + mkdir -p $WIT_DIR || return 1 + cd $WIT_DIR || return 1 + + imagetoolBinDir=$WIT_DIR/imagetool/bin + if [ -f $imagetoolBinDir/imagetool.sh ]; then + echo @@ "Info: imagetool.sh already exist in ${imagetoolBinDir}. Skipping WIT installation." + else + install_wit + fi + + export WLSIMG_CACHEDIR="$WIT_DIR/imagetool-cache" + + # Check existing imageTool cache entry for WDT: + # - if there is already an entry, and the WDT installer file specified in the cache entry exists, skip WDT installation + # - if file in cache entry doesn't exist, delete cache entry, install WDT, and add WDT installer to cache + # - if entry does not exist, install WDT, and add WDT installer to cache + if [ "$WDT_VERSION" == "LATEST" ]; then + wdtCacheVersion="latest" + else + wdtCacheVersion=$WDT_VERSION + fi + + local listItems=$( ${imagetoolBinDir}/imagetool.sh cache listItems | grep "wdt_${wdtCacheVersion}" ) + + if [ ! -z "$listItems" ]; then + local wdt_file_path_in_cache=$(echo $listItems | sed 's/.*=\(.*\)/\1/') + if [ -f "$wdt_file_path_in_cache" ]; then + skip_wdt_install=true + else + echo @@ "Info: imageTool cache contains an entry for WDT zip at $wdt_file_path_in_cache which does not exist. Removing from cache entry." + ${imagetoolBinDir}/imagetool.sh cache deleteEntry \ + --key wdt_${wdtCacheVersion} + fi + fi + + if [ -z "$skip_wdt_install" ]; then + echo @@ "Info: imageTool cache does not contain a valid entry for wdt_${wdtCacheVersion}. Installing WDT" + setup_wdt_shared_dir || return 1 + install_wdt || return 1 + ${imagetoolBinDir}/imagetool.sh cache addInstaller \ + --type wdt \ + --version $WDT_VERSION \ + --path $WDT_DIR/$WDT_INSTALL_ZIP_FILE || return 1 + else + echo @@ "Info: imageTool cache already contains entry ${listItems}. Skipping WDT installation." + fi + + cd $save_dir + + echo @@ "Info: Install succeeded, imagetool install is in the $WIT_DIR/imagetool directory." + return 0 +} + +function encrypt_model { + # + # run encryptModel.sh from WDT to encrypt model and properties files + # + local domainOutputDirFullPath=${1} # full path to directory where the model, encrypt file, and domain properties files are + local model_file=${2} # path to file containing encryption key relative to ${domainOutputDirFullPath} + local encrypt_key_file=${3} # path to file containing encryption key relative to ${domainOutputDirFullPath} + local domain_properties_file=${4} # path to domain properties file relative to ${domainOutputDirFullPath} + local oracle_home="$ORACLE_HOME" + + echo @@ "Info: encrypt passwords in the variables file at ${domainOutputDirFullPath}/${domain_properties_file} using encryption key from create-domain.sh argument written to file: ${encrypt_key_file}" + + cmd=" + cat /shared/${encrypt_key_file} /shared/${encrypt_key_file} | + /wdt/bin/encryptModel.sh \ + -oracle_home ${oracle_home} \ + -model_file /shared/${model_file} \ + -variable_file /shared/${domain_properties_file} + " + echo $cmd > ${domainOutputDirFullPath}/cmd.sh + chmod 755 ${domainOutputDirFullPath}/cmd.sh + echo @@ "Info: Encrypt Model: About to run the following command in container with image ${domainHomeImageBase}:" + cat ${domainOutputDirFullPath}/cmd.sh + + chmod 766 ${domainOutputDirFullPath}/${domain_properties_file} + docker run -it --rm -v ${domainOutputDirFullPath}:/shared -v ${WDT_DIR}/weblogic-deploy:/wdt ${domainHomeImageBase} /bin/bash -c /shared/cmd.sh || return 1 + + # clean up the generated files + rm ${domainOutputDirFullPath}/cmd.sh + + echo @@ "Info: encrypt_model Completed" +} + + diff --git a/OracleWebCenterPortal/kubernetes/create-kubernetes-secrets/create-azure-storage-credentials-secret.sh b/OracleWebCenterPortal/kubernetes/create-kubernetes-secrets/create-azure-storage-credentials-secret.sh new file mode 100644 index 000000000..8e6d3d947 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-kubernetes-secrets/create-azure-storage-credentials-secret.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description +# This sample script creates a Kubernetes secret for Azure Storage to use Azure file share on AKS. +# +# The following pre-requisites must be handled prior to running this script: +# * The kubernetes namespace must already be created +# + +script="${BASH_SOURCE[0]}" + +# +# Function to exit and print an error message +# $1 - text of message +function fail { + echo [ERROR] $* + exit 1 +} + +# Try to execute kubectl to see whether kubectl is available +function validateKubectlAvailable { + if ! [ -x "$(command -v kubectl)" ]; then + fail "kubectl is not installed" + fi +} + +function usage { + echo usage: ${script} -c storageAccountName -k storageAccountKey [-s secretName] [-n namespace] [-h] + echo " -a storage account name, must be specified." + echo " -k storage account key, must be specified." + echo " -s secret name, optional. Use azure-secret if not specified." + echo " -n namespace, optional. Use the default namespace if not specified." + echo " -h Help" + exit $1 +} + +# +# Parse the command line options +# +secretName=azure-secret +namespace=default +while getopts "ha:k:s:n:" opt; do + case $opt in + a) storageAccountName="${OPTARG}" + ;; + k) storageAccountKey="${OPTARG}" + ;; + s) secretName="${OPTARG}" + ;; + n) namespace="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${storageAccountName} ]; then + echo "${script}: -e must be specified." + missingRequiredOption="true" +fi + +if [ -z ${storageAccountKey} ]; then + echo "${script}: -p must be specified." + missingRequiredOption="true" +fi + +if [ "${missingRequiredOption}" == "true" ]; then + usage 1 +fi + +# check and see if the secret already exists +result=`kubectl get secret ${secretName} -n ${namespace} --ignore-not-found=true | grep ${secretName} | wc | awk ' { print $1; }'` +if [ "${result:=Error}" != "0" ]; then + fail "The secret ${secretName} already exists in namespace ${namespace}." +fi + +# create the secret +kubectl -n $namespace create secret generic $secretName \ + --from-literal=azurestorageaccountname=$storageAccountName \ + --from-literal=azurestorageaccountkey=$storageAccountKey + +# Verify the secret exists +SECRET=`kubectl get secret ${secretName} -n ${namespace} | grep ${secretName} | wc | awk ' { print $1; }'` +if [ "${SECRET}" != "1" ]; then + fail "The secret ${secretName} was not found in namespace ${namespace}" +fi + +echo "The secret ${secretName} has been successfully created in the ${namespace} namespace." diff --git a/OracleWebCenterPortal/kubernetes/create-kubernetes-secrets/create-docker-credentials-secret.sh b/OracleWebCenterPortal/kubernetes/create-kubernetes-secrets/create-docker-credentials-secret.sh new file mode 100644 index 000000000..48f113b93 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-kubernetes-secrets/create-docker-credentials-secret.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description +# This sample script creates a Kubernetes secret for container registry credentials for use with the WLS Operator on AKS. +# +# The following pre-requisites must be handled prior to running this script: +# * The kubernetes namespace must already be created +# + +script="${BASH_SOURCE[0]}" + +# +# Function to exit and print an error message +# $1 - text of message +function fail { + echo [ERROR] $* + exit 1 +} + +# Try to execute kubectl to see whether kubectl is available +function validateKubectlAvailable { + if ! [ -x "$(command -v kubectl)" ]; then + fail "kubectl is not installed" + fi +} + +function usage { + echo usage: ${script} -e email -p password -u username [-s secretName] [-d dockerServer] [-n namespace] [-h] + echo " -e email, must be specified." + echo " -p password, must be specified." + echo " -u username, must be specified." + echo " -s secret name, optional, Use regcred if not specified." + echo " -d docker server, optional, Use docker.io if not specified." + echo " -n namespace, optional. Use the default namespace if not specified" + echo " -h Help" + exit $1 +} + +# +# Parse the command line options +# +secretName=regcred +namespace=default +dockerServer=container-registry.oracle.com +while getopts "he:p:u:n:d:s:d:" opt; do + case $opt in + e) email="${OPTARG}" + ;; + p) password="${OPTARG}" + ;; + u) username="${OPTARG}" + ;; + s) secretName="${OPTARG}" + ;; + d) dockerServer="${OPTARG}" + ;; + n) namespace="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${email} ]; then + echo "${script}: -e must be specified." + missingRequiredOption="true" +fi + +if [ -z ${password} ]; then + echo "${script}: -p must be specified." + missingRequiredOption="true" +fi + +if [ -z ${username} ]; then + echo "${script}: -u must be specified." + missingRequiredOption="true" +fi + +if [ "${missingRequiredOption}" == "true" ]; then + usage 1 +fi + +# check and see if the secret already exists +result=`kubectl get secret ${secretName} -n ${namespace} --ignore-not-found=true | grep ${secretName} | wc | awk ' { print $1; }'` +if [ "${result:=Error}" != "0" ]; then + fail "The secret ${secretName} already exists in namespace ${namespace}." +fi + +# create the secret +kubectl -n $namespace create secret docker-registry $secretName \ + --docker-email=$email \ + --docker-password=$password \ + --docker-server=$dockerServer \ + --docker-username=$username + +# Verify the secret exists +SECRET=`kubectl get secret ${secretName} -n ${namespace} | grep ${secretName} | wc | awk ' { print $1; }'` +if [ "${SECRET}" != "1" ]; then + fail "The secret ${secretName} was not found in namespace ${namespace}" +fi + +echo "The secret ${secretName} has been successfully created in the ${namespace} namespace." diff --git a/OracleWebCenterPortal/kubernetes/create-oracle-db-service/README.md b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/README.md new file mode 100644 index 000000000..042f8fe11 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/README.md @@ -0,0 +1,76 @@ +# Managing Oracle Database Service for OracleWebCenterPortal + +The sample scripts in this directory demonstrate how to: +* Start an Oracle Database (DB) service in a Kubernetes cluster. +* Stop an Oracle DB service in a Kubernetes cluster. + +## Start an Oracle Database service in a Kubernetes cluster + +Use this script to create an Oracle Database service in a Kubernetes Namespace with the default credentials, in the Oracle Database Slim image. + +The script assumes that either the image, `container-registry.oracle.com/database/enterprise:12.2.0.1-slim`, is available in the Docker repository, or an `ImagePullSecret` is created for `container-registry.oracle.com`. To create a secret for accessing `container-registry.oracle.com`, see the script `create-image-pull-secret.sh`. + +``` + +$ ./start-db-service.sh -h +usage: ./start-db-service.sh -p -i -s -n [-h] + -i Oracle DB Image (optional) + (default: container-registry.oracle.com/database/enterprise:12.2.0.1-slim) + -p DB Service NodePort (optional) + (default: 30011, set to 'none' to deploy service without a NodePort) + -s DB Image PullSecret (optional) + (default: docker-store) + -n Configurable Kubernetes NameSpace for Oracle DB Service (optional)" + (default: default) + -h Help + +$ ./start-db-service.sh +NodePort[30011] ImagePullSecret[docker-store] Image[container-registry.oracle.com/database/enterprise:12.2.0.1-slim] +deployment.extensions/oracle-db created +service/oracle-db created +[oracle-db-54667dfd5f-76sxf] already initialized .. +Checking Pod READY column for State [1/1] +Pod [oracle-db-54667dfd5f-76sxf] Status is Ready Iter [1/60] +NAME READY STATUS RESTARTS AGE +oracle-db-54667dfd5f-76sxf 1/1 Running 0 8s +NAME READY STATUS RESTARTS AGE +oracle-db-54667dfd5f-76sxf 1/1 Running 0 8s +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +kubernetes ClusterIP 10.96.0.1 443/TCP 27d +oracle-db NodePort 10.99.58.137 1521:30011/TCP 9s +Oracle DB service is RUNNING with NodePort [30011] + +``` + +For creating a OracleWebCenterPortal domain, you can use the database connection string, `oracle-db.default.svc.cluster.local:1521/devpdb.k8s`,as `rcuDatabaseURL` parameter in the `domain.input.yaml` file. + +Note: oracle-db.default.svc.cluster.local:1521/devpdb.k8s can be used as rcuDatabaseURL if the Oracle DB Service is started in `default` NameSpace. For custom NameSpace the URL need to be modified accrodingly e.g. oracle-db.[namespace].svc.cluster.local:1521/devpdb.k8s + +You can access the database through the NodePort outside of the Kubernetes cluster, using the URL `:30011/devpdb.k8s`. + +**Note**: To create a OracleWebCenterPortal domain image, the domain-in-image model needs a public database URL as an `rcuDatabaseURL` parameter. + +## Stop an Oracle Database service in a Kubernetes cluster + +Use this script to stop the Oracle Database service you created using the `start-db-service.sh` script. + +``` +$ ./stop-db-service.sh -h +usage: stop-db-service.sh -n namespace [-h] + -n Kubernetes NameSpace for Oracle DB Service to be Stopped (optional) + (default: default) + -h Help + +Note: Here the NameSpace refers to the NameSpace used in start-db-service.sh + +$ ./stop-db-service.sh +deployment.extensions "oracle-db" deleted +service "oracle-db" deleted +Checking Status for Pod [oracle-db-756f9b99fd-gvv46] in namesapce [default] +Pod [oracle-db-756f9b99fd-gvv46] Status [Terminating] +Pod [oracle-db-756f9b99fd-gvv46] Status [Terminating] +Pod [oracle-db-756f9b99fd-gvv46] Status [Terminating] +Error from server (NotFound): pods "oracle-db-756f9b99fd-gvv46" not found +Pod [oracle-db-756f9b99fd-gvv46] removed from nameSpace [default] +``` + diff --git a/OracleWebCenterPortal/kubernetes/create-oracle-db-service/common/checkDbState.sh b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/common/checkDbState.sh new file mode 100644 index 000000000..9ce5aa3d3 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/common/checkDbState.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +logfile="/home/oracle/setup/log/setupDB.log" +max=30 +counter=0 +while [ $counter -le ${max} ] +do + grep "Done ! The database is ready for use ." $logfile + [[ $? == 0 ]] && break; + ((counter++)) + echo "[$counter/${max}] Retrying for Oracle Database Availability..." + sleep 10 +done + +if [ $counter -gt ${max} ]; then + echo "[ERRORR] Oracle DB Service is not ready after [${max}] iterations ..." + exit -1 +fi + diff --git a/OracleWebCenterPortal/kubernetes/create-oracle-db-service/common/oracle.db.yaml b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/common/oracle.db.yaml new file mode 100644 index 000000000..4185471f3 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/common/oracle.db.yaml @@ -0,0 +1,78 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Service +metadata: + name: oracle-db + namespace: default +spec: + ports: + - name: tns + port: 1521 + protocol: TCP + targetPort: 1521 + nodePort: 30011 + selector: + app.kubernetes.io/instance: dev + app.kubernetes.io/name: oracle-db + sessionAffinity: None + type: NodePort +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: oracle-db + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: dev + app.kubernetes.io/name: oracle-db + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app.kubernetes.io/instance: dev + app.kubernetes.io/name: oracle-db + spec: + containers: + - env: + - name: DB_SID + value: devcdb + - name: DB_PDB + value: devpdb + - name: DB_DOMAIN + value: k8s + - name: DB_BUNDLE + value: basic + image: container-registry.oracle.com/database/enterprise:12.2.0.1-slim + imagePullPolicy: IfNotPresent + name: oracle-db + ports: + - containerPort: 1521 + name: tns + protocol: TCP + resources: + limits: + cpu: "2" + memory: "6Gi" + ephemeral-storage: "8Gi" + requests: + cpu: 500m + ephemeral-storage: "6Gi" + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + imagePullSecrets: + - name: docker-store + diff --git a/OracleWebCenterPortal/kubernetes/create-oracle-db-service/create-image-pull-secret.sh b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/create-image-pull-secret.sh new file mode 100644 index 000000000..3c7db8bc5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/create-image-pull-secret.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Create ImagePullSecret to pull Oracle DB and OracleWebCenterPortal Image + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" + +function usage { + echo "usage: ${script} -u -p -e -s [-h]" + echo " -u Oracle Container Registry User Name (needed)" + echo " -p Oracle Container Registry Password (needed)" + echo " -e email (needed)" + echo " -s Generated Secret (optional) " + echo " (default: docker-store) " + echo " -h Help" + exit $1 +} + +while getopts ":u:p:s:e:" opt; do + case $opt in + u) username="${OPTARG}" + ;; + p) password="${OPTARG}" + ;; + e) email="${OPTARG}" + ;; + s) secert="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${username} ]; then + echo "${script}: -u must be specified." + usage 1 +fi + +if [ -z ${password} ]; then + echo "${script}: -p must be specified." + usage 1 +fi + +if [ -e ${email} ]; then + echo "${script}: -p must be specified." + usage 1 +fi + +if [ -z ${secret} ]; then + secret="docker-store" +fi + +kubectl delete secret/${secret} --ignore-not-found +echo "Creating ImagePullSecret on container-registry.oracle.com" +kubectl create secret docker-registry ${secret} --docker-server=container-registry.oracle.com --docker-username=${username} --docker-password=${password} --docker-email=${email} + diff --git a/OracleWebCenterPortal/kubernetes/create-oracle-db-service/start-db-service.sh b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/start-db-service.sh new file mode 100644 index 000000000..9a522d4eb --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/start-db-service.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Bring up Oracle DB Instance in [default] NameSpace with a NodePort Service + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/../common/utility.sh + +function usage { + echo "usage: ${script} -p -i -s -n [-h]" + echo " -i Oracle DB Image (optional)" + echo " (default: container-registry.oracle.com/database/enterprise:12.2.0.1-slim)" + echo " -p DB Service NodePort (optional)" + echo " (default: 30011, set to 'none' to deploy service without a NodePort)" + echo " -s DB Image PullSecret (optional)" + echo " (default: docker-store) " + echo " -n Configurable Kubernetes NameSpace for Oracle DB Service (optional)" + echo " (default: default) " + echo " -h Help" + exit $1 +} + +while getopts ":h:p:s:i:n:" opt; do + case $opt in + p) nodeport="${OPTARG}" + ;; + s) pullsecret="${OPTARG}" + ;; + i) dbimage="${OPTARG}" + ;; + n) namespace="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${nodeport} ]; then + nodeport=30011 +fi + +if [ -z ${pullsecret} ]; then + pullsecret="docker-store" +fi + +if [ -z ${namespace} ]; then + namespace="default" +fi + +echo "Checking Status for NameSpace [$namespace]" +domns=`kubectl get ns ${namespace} | grep ${namespace} | awk '{print $1}'` +if [ -z ${domns} ]; then + echo "Adding NameSpace[$namespace] to Kubernetes Cluster" + kubectl create namespace ${namespace} + sleep 5 +else + echo "Skipping the NameSpace[$namespace] Creation ..." +fi + +if [ -z ${dbimage} ]; then + dbimage="container-registry.oracle.com/database/enterprise:12.2.0.1-slim" +fi + +echo "NodePort[$nodeport] ImagePullSecret[$pullsecret] Image[${dbimage}] NameSpace[${namespace}]" + +# Modify ImagePullSecret and DatabaseImage based on input +sed -i -e '$d' ${scriptDir}/common/oracle.db.yaml +echo ' - name: docker-store' >> ${scriptDir}/common/oracle.db.yaml +sed -i -e "s?name: docker-store?name: ${pullsecret}?g" ${scriptDir}/common/oracle.db.yaml +sed -i -e "s?image:.*?image: ${dbimage}?g" ${scriptDir}/common/oracle.db.yaml +sed -i -e "s?namespace:.*?namespace: ${namespace}?g" ${scriptDir}/common/oracle.db.yaml + +# Modify the NodePort based on input +if [ "${nodeport}" = "none" ]; then + sed -i -e "s? nodePort:? #nodePort:?g" ${scriptDir}/common/oracle.db.yaml + sed -i -e "s? type:.*NodePort? #type: NodePort?g" ${scriptDir}/common/oracle.db.yaml +else + sed -i -e "s?[#]*nodePort:.*?nodePort: ${nodeport}?g" ${scriptDir}/common/oracle.db.yaml + sed -i -e "s?[#]*type:.*NodePort?type: NodePort?g" ${scriptDir}/common/oracle.db.yaml # default type is ClusterIP +fi + +kubectl delete service oracle-db -n ${namespace} --ignore-not-found +kubectl apply -f ${scriptDir}/common/oracle.db.yaml + +dbpod=`kubectl get po -n ${namespace} | grep oracle-db | cut -f1 -d " " ` + +checkPod ${dbpod} ${namespace} +checkPodState ${dbpod} ${namespace} "1/1" +checkService oracle-db ${namespace} + +kubectl get po -n ${namespace} +kubectl get service -n ${namespace} + +kubectl cp ${scriptDir}/common/checkDbState.sh -n ${namespace} ${dbpod}:/home/oracle/ +kubectl exec -it ${dbpod} -n ${namespace} /bin/bash /home/oracle/checkDbState.sh +if [ $? != 0 ]; then + echo "######################"; + echo "[ERROR] Could not create Oracle DB Service, check the pod log for pod ${dbpod} in namespace ${namespace}"; + echo "######################"; + exit -3; +fi + +if [ ! "${nodeport}" = "none" ]; then + echo "Oracle DB Service is RUNNING with NodePort [${nodeport}]" +else + echo "Oracle DB Service is RUNNING and does not specify a public NodePort" +fi +echo "Oracle DB Service URL [oracle-db.${namespace}.svc.cluster.local:1521/devpdb.k8s]" + diff --git a/OracleWebCenterPortal/kubernetes/create-oracle-db-service/stop-db-service.sh b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/stop-db-service.sh new file mode 100644 index 000000000..7ab14928c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-oracle-db-service/stop-db-service.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Drop the DB Service created by start-db-service.sh + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/../common/utility.sh + +function usage { + echo "usage: ${script} -n namespace [-h]" + echo " -n Kubernetes NameSpace for Oracle DB Service to be Stopped (optional)" + echo " (default: default) " + echo " -h Help" + exit $1 +} + +while getopts ":h:n:" opt; do + case $opt in + n) namespace="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + + +if [ -z ${namespace} ]; then + namespace=default +fi + + +dbpod=`kubectl get po -n ${namespace} | grep oracle-db | cut -f1 -d " " ` +kubectl delete -f ${scriptDir}/common/oracle.db.yaml --ignore-not-found + +if [ -z ${dbpod} ]; then + echo "Couldn't find oracle-db pod in [${namespace}] namesapce" +else + checkPodDelete ${dbpod} ${namespace} + kubectl delete svc/oracle-db -n ${namespace} --ignore-not-found +fi + diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-credentials/README.md b/OracleWebCenterPortal/kubernetes/create-rcu-credentials/README.md new file mode 100644 index 000000000..962f331c3 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-credentials/README.md @@ -0,0 +1,56 @@ +# Creating RCU credentials for a OracleWebCenterPortal domain + +This sample demonstrates how to create a Kubernetes secret containing the +RCU credentials for a OracleWebCenterPortal domain. The operator expects this secret to be +named following the pattern `domainUID-rcu-credentials`, where `domainUID` +is the unique identifier of the domain. It must be in the same namespace +that the domain will run in. + +To use the sample, run the command: + +``` +$ ./create-rcu-credentials.sh \ + -u username \ + -p password \ + -a sys_username \ + -q sys_password \ + -d domainUID \ + -n namespace \ + -s secretName +``` + +The parameters are as follows: + +``` + -u username for schema owner (regular user), must be specified. + -p password for schema owner (regular user), must be specified. + -a username for SYSDBA user, must be specified. + -q password for SYSDBA user, must be specified. + -d domainUID, optional. The default value is wcp-domain. If specified, the secret will be labeled with the domainUID unless the given value is an empty string. + -n namespace, optional. Use the wcpns namespace if not specified. + -s secretName, optional. If not specified, the secret name will be determined based on the domainUID value. +``` + +This creates a `generic` secret containing the user name and password as literal values. + +You can check the secret with the `kubectl describe secret` command. An example is shown below, +including the output: + +``` +$ kubectl -n wcpns describe secret wcp-domain-rcu-credentials -o yaml +Name: wcp-domain-rcu-credentials +Namespace: wcpns +Labels: weblogic.domainName=wcp-domain + weblogic.domainUID=wcp-domain +Annotations: + +Type: Opaque + +Data +==== +password: 12 bytes +sys_password: 12 bytes +sys_username: 3 bytes +username: 4 bytes +``` + diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-credentials/create-rcu-credentials.sh b/OracleWebCenterPortal/kubernetes/create-rcu-credentials/create-rcu-credentials.sh new file mode 100644 index 000000000..f1b492bbd --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-credentials/create-rcu-credentials.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description +# This sample script creates a Kubernetes secret for RCU credentials. +# +# The following pre-requisites must be handled prior to running this script: +# * The kubernetes namespace must already be created +# +# Secret name determination +# 1) secretName - if specified +# 2) wcp-domain-rcu-credentials - if secretName and domainUID are both not specified. This is the default out-of-the-box. +# 3) -rcu-credentials - if secretName is not specified, and domainUID is specified. +# 4) rcu-credentials - if secretName is not specified, and domainUID is specified as "". +# +# The generated secret will be labeled with +# weblogic.domainUID=$domainUID +# and +# weblogic.domainName=$domainUID +# Where the $domainUID is the value of the -d command line option, unless the value supplied is an empty String "" +# + +script="${BASH_SOURCE[0]}" + +# +# Function to exit and print an error message +# $1 - text of message +function fail { + echo [ERROR] $* + exit 1 +} + +# Try to execute kubectl to see whether kubectl is available +function validateKubectlAvailable { + if ! [ -x "$(command -v kubectl)" ]; then + fail "kubectl is not installed" + fi +} + +function usage { + echo usage: ${script} -u username -p password -a sysuser -q syspassword [-d domainUID] [-n namespace] [-s secretName] [-h] + echo " -u username for schema owner (regular user), must be specified." + echo " -p password for schema owner (regular user), must be specified." + echo " -a username for SYSDBA user, must be specified." + echo " -q password for SYSDBA user, must be specified." + echo " -d domainUID, optional. The default value is wcp-domain. If specified, the secret will be labeled with the domainUID unless the given value is an empty string." + echo " -n namespace, optional. Use the wcpns namespace if not specified" + echo " -s secretName, optional. If not specified, the secret name will be determined based on the domainUID value" + echo " -h Help" + exit $1 +} + +# +# Parse the command line options +# +domainUID=wcp-domain +namespace=wcpns +while getopts "hu:p:n:d:s:q:a:" opt; do + case $opt in + u) username="${OPTARG}" + ;; + p) password="${OPTARG}" + ;; + a) sys_username="${OPTARG}" + ;; + q) sys_password="${OPTARG}" + ;; + n) namespace="${OPTARG}" + ;; + d) domainUID="${OPTARG}" + ;; + s) secretName="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z $secretName ]; then + if [ -z $domainUID ]; then + secretName=rcu-credentials + else + secretName=$domainUID-rcu-credentials + fi +fi + +if [ -z ${username} ]; then + echo "${script}: -u must be specified." + missingRequiredOption="true" +fi + +if [ -z ${password} ]; then + echo "${script}: -p must be specified." + missingRequiredOption="true" +fi + +if [ -z ${sys_username} ]; then + echo "${script}: -s must be specified." + missingRequiredOption="true" +fi + +if [ -z ${sys_password} ]; then + echo "${script}: -q must be specified." + missingRequiredOption="true" +fi + +if [ "${missingRequiredOption}" == "true" ]; then + usage 1 +fi + +# check and see if the secret already exists +result=`kubectl get secret ${secretName} -n ${namespace} --ignore-not-found=true | grep ${secretName} | wc | awk ' { print $1; }'` +if [ "${result:=Error}" != "0" ]; then + fail "The secret ${secretName} already exists in namespace ${namespace}." +fi + +# create the secret +kubectl -n $namespace create secret generic $secretName \ + --from-literal=username=$username \ + --from-literal=password=$password \ + --from-literal=sys_username=$sys_username \ + --from-literal=sys_password=$sys_password + +# label the secret with domainUID if needed +if [ ! -z $domainUID ]; then + kubectl label secret ${secretName} -n $namespace weblogic.domainUID=$domainUID weblogic.domainName=$domainUID +fi + +# Verify the secret exists +SECRET=`kubectl get secret ${secretName} -n ${namespace} | grep ${secretName} | wc | awk ' { print $1; }'` +if [ "${SECRET}" != "1" ]; then + fail "The secret ${secretName} was not found in namespace ${namespace}" +fi + +echo "The secret ${secretName} has been successfully created in the ${namespace} namespace." + diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-schema/README.md b/OracleWebCenterPortal/kubernetes/create-rcu-schema/README.md new file mode 100644 index 000000000..38b0068fa --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-schema/README.md @@ -0,0 +1,219 @@ +# Managing RCU schema for a OracleWebCenterPortal domain + +The sample scripts in this directory demonstrate how to: +* Create an RCU schema in the Oracle DB that will be used by a OracleWebCenterPortal domain. +* Delete the RCU schema in the Oracle DB used by a OracleWebCenterPortal domain. + +## Start an Oracle Database service in a Kubernetes cluster + +Use the script ``samples/scripts/create-oracle-db-service/start-db-service.sh`` + +For creating a OracleWebCenterPortal domain, you can use the Database connection string, `oracle-db.default.svc.cluster.local:1521/devpdb.k8s`, as an `rcuDatabaseURL` parameter in the `domain.input.yaml` file. + +You can access the Database through the NodePort outside of the Kubernetes cluster, using the URL `:30011/devpdb.k8s`. + +**Note**: To create a OracleWebCenterPortal domain image, the domain-in-image model needs a public Database URL as an `rcuDatabaseURL` parameter. + + +## Create the RCU schema in the Oracle Database + +This script generates the RCU schema based `schemaPrefix` and `dburl`. + +The script assumes that either the image, `oracle/wcportal:12.2.1.4`, is available in the nodes or an `ImagePullSecret` is created to pull the image. To create a secret, see the script `create-image-pull-secret.sh`. + +``` +$ ./create-rcu-schema.sh -h +usage: ./create-rcu-schema.sh -s -t -d -i -u -p -n -q -r -o -c [-h] + -s RCU Schema Prefix (required) + -t RCU Schema Type (optional) + (supported values: wcp,wcpp) + -d RCU Oracle Database URL (optional) + (default: oracle-db.default.svc.cluster.local:1521/devpdb.k8s) + -p OracleWebCenterPortal ImagePullSecret (optional) + (default: none) + -i OracleWebCenterPortal Image (optional) + (default: oracle/wcportal:12.2.1.4) + -u OracleWebCenterPortal ImagePullPolicy (optional) + (default: IfNotPresent) + -n Namespace for RCU pod (optional) + (default: default) + -q password for database SYSDBA user. (optional) + (default: Oradoc_db1) + -r password for all schema owner (regular user). (optional) + (default: Oradoc_db1) + -o Output directory for the generated YAML file. (optional) + (default: rcuoutput) + -c Comma-separated variables in the format variablename=value. (optional). + (default: none) + -h Help + +$ ./create-rcu-schema.sh -s domain1 +ImagePullSecret[none] Image[oracle/wcportal:12.2.1.4] dburl[oracle-db.default.svc.cluster.local:1521/devpdb.k8s] rcuType[wcp] customVariables[none] +pod/rcu created +[rcu] already initialized .. +Checking Pod READY column for State [1/1] +Pod [rcu] Status is Ready Iter [1/60] +NAME READY STATUS RESTARTS AGE +rcu 1/1 Running 0 6s +NAME READY STATUS RESTARTS AGE +rcu 1/1 Running 0 11s +CLASSPATH=/u01/jdk/lib/tools.jar:/u01/oracle/wlserver/modules/features/wlst.wls.classpath.jar: + +PATH=/u01/oracle/wlserver/server/bin:/u01/oracle/wlserver/../oracle_common/modules/thirdparty/org.apache.ant/1.10.5.0.0/apache-ant-1.10.5/bin:/u01/jdk/jre/bin:/u01/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/u01/jdk/bin:/u01/oracle/oracle_common/common/bin:/u01/oracle/wlserver/common/bin:/u01/oracle:/u01/oracle/wlserver/../oracle_common/modules/org.apache.maven_3.2.5/bin + +Your environment has been set. +Check if the DB Service is ready to accept request +DB Connection String [oracle-db.default.svc.cluster.local:1521/devpdb.k8s], schemaPrefix [wcp-domain] rcuType [wcp] + +**** Success!!! **** + +You can connect to the database in your app using: + + java.util.Properties props = new java.util.Properties(); + props.put("user", "sys as sysdba"); + props.put("password", "Oradoc_db1"); + java.sql.Driver d = + Class.forName("oracle.jdbc.OracleDriver").newInstance(); + java.sql.Connection conn = + Driver.connect("sys as sysdba", props); +Creating RCU Schema for OracleWebCenterPortal Domain ... +Extra RCU Schema Component Choosen[] + +Processing command line .... + +Repository Creation Utility - Checking Prerequisites +Checking Component Prerequisites +Repository Creation Utility - Creating Tablespaces +Validating and Creating Tablespaces +Create tablespaces in the repository database +Repository Creation Utility - Create +Repository Create in progress. +Executing pre create operations + Percent Complete: 20 + Percent Complete: 20 + ..... + Percent Complete: 96 + Percent Complete: 100 + ..... +Executing post create operations + +Repository Creation Utility: Create - Completion Summary + +Database details: +----------------------------- +Host Name : oracle-db.default.svc.cluster.local +Port : 1521 +Service Name : DEVPDB.K8S +Connected As : sys +Prefix for (prefixable) Schema Owners : DOMAIN1 +RCU Logfile : /tmp/RCU2020-05-01_14-35_1160633335/logs/rcu.log + +Component schemas created: +----------------------------- +Component Status Logfile + +Common Infrastructure Services Success /tmp/RCU2020-05-01_14-35_1160633335/logs/stb.log +Oracle Platform Security Services Success /tmp/RCU2020-05-01_14-35_1160633335/logs/opss.log +Audit Services Success /tmp/RCU2020-05-01_14-35_1160633335/logs/iau.log +Audit Services Append Success /tmp/RCU2020-05-01_14-35_1160633335/logs/iau_append.log +Audit Services Viewer Success /tmp/RCU2020-05-01_14-35_1160633335/logs/iau_viewer.log +Metadata Services Success /tmp/RCU2020-05-01_14-35_1160633335/logs/mds.log +WebLogic Services Success /tmp/RCU2020-05-01_14-35_1160633335/logs/wls.log + +Repository Creation Utility - Create : Operation Completed +[INFO] Modify the domain.input.yaml to use [oracle-db.default.svc.cluster.local:1521/devpdb.k8s] as rcuDatabaseURL and [domain1] as rcuSchemaPrefix +``` + +## Drop the RCU schema from the Oracle Database + +Use this script to drop the RCU schema based `schemaPrefix` and `dburl`. + +``` +$ ./drop-rcu-schema.sh -h +usage: ./drop-rcu-schema.sh -s -d -n -q -r [-h] + -s RCU Schema Prefix (required) + -t RCU Schema Type (optional) + (supported values: wcp,wcpp) + -d Oracle Database URL (optional) + (default: oracle-db.default.svc.cluster.local:1521/devpdb.k8s) + -n Namespace where RCU pod is deployed (optional) + (default: default) + -q password for database SYSDBA user. (optional) + (default: Oradoc_db1) + -r password for all schema owner (regular user). (optional) + (default: Oradoc_db1) + -c Comma-separated variables in the format variablename=value. (optional). + (default: none) + -h Help + +$ ./drop-rcu-schema.sh -s domain1 +CLASSPATH=/u01/jdk/lib/tools.jar:/u01/oracle/wlserver/modules/features/wlst.wls.classpath.jar: + +PATH=/u01/oracle/wlserver/server/bin:/u01/oracle/wlserver/../oracle_common/modules/thirdparty/org.apache.ant/1.10.5.0.0/apache-ant-1.10.5/bin:/u01/jdk/jre/bin:/u01/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/u01/jdk/bin:/u01/oracle/oracle_common/common/bin:/u01/oracle/wlserver/common/bin:/u01/oracle:/u01/oracle/wlserver/../oracle_common/modules/org.apache.maven_3.2.5/bin + +Your environment has been set. +Check if the DB Service is ready to accept request +DB Connection String [oracle-db.default.svc.cluster.local:1521/devpdb.k8s] schemaPrefix [domain1] rcuType[wcp] + +**** Success!!! **** + +You can connect to the database in your app using: + + java.util.Properties props = new java.util.Properties(); + props.put("user", "sys as sysdba"); + props.put("password", "Oradoc_db1"); + java.sql.Driver d = + Class.forName("oracle.jdbc.OracleDriver").newInstance(); + java.sql.Connection conn = + Driver.connect("sys as sysdba", props); +Dropping RCU Schema for OracleWebCenterPortal Domain ... +Extra RCU Schema Component(s) Choosen[] + +Processing command line .... +Repository Creation Utility - Checking Prerequisites +Checking Global Prerequisites +Repository Creation Utility - Checking Prerequisites +Checking Component Prerequisites +Repository Creation Utility - Drop +Repository Drop in progress. + Percent Complete: 2 + Percent Complete: 14 + ..... + Percent Complete: 99 + Percent Complete: 100 + ..... + +Repository Creation Utility: Drop - Completion Summary + +Database details: +----------------------------- +Host Name : oracle-db.default.svc.cluster.local +Port : 1521 +Service Name : DEVPDB.K8S +Connected As : sys +Prefix for (prefixable) Schema Owners : DOMAIN1 +RCU Logfile : /tmp/RCU2020-05-01_14-42_651700358/logs/rcu.log + +Component schemas dropped: +----------------------------- +Component Status Logfile + +Common Infrastructure Services Success /tmp/RCU2020-05-01_14-42_651700358/logs/stb.log +Oracle Platform Security Services Success /tmp/RCU2020-05-01_14-42_651700358/logs/opss.log +Audit Services Success /tmp/RCU2020-05-01_14-42_651700358/logs/iau.log +Audit Services Append Success /tmp/RCU2020-05-01_14-42_651700358/logs/iau_append.log +Audit Services Viewer Success /tmp/RCU2020-05-01_14-42_651700358/logs/iau_viewer.log +Metadata Services Success /tmp/RCU2020-05-01_14-42_651700358/logs/mds.log +WebLogic Services Success /tmp/RCU2020-05-01_14-42_651700358/logs/wls.log + +Repository Creation Utility - Drop : Operation Completed +pod "rcu" deleted +Checking Status for Pod [rcu] in namesapce [default] +Error from server (NotFound): pods "rcu" not found +Pod [rcu] removed from nameSpace [default] +``` + +## Stop an Oracle Database service in a Kubernetes cluster + +Use the script ``samples/scripts/create-oracle-db-service/stop-db-service.sh`` + diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/createRepository.sh b/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/createRepository.sh new file mode 100644 index 000000000..61da67e55 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/createRepository.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +. /u01/oracle/wlserver/server/bin/setWLSEnv.sh + +echo "Check if the DB Service is ready to accept request " +connectString=${1:-oracle-db.default.svc.cluster.local:1521/devpdb.k8s} +schemaPrefix=${2:-wcp-domain} +rcuType=${3:-wcp} +sysPassword=${4:-Oradoc_db1} +customVariables=${5:-none} + +echo "DB Connection String [$connectString], schemaPrefix [${schemaPrefix}] rcuType [${rcuType}] customVariables [${customVariables}]" + +max=100 +counter=0 +while [ $counter -le ${max} ] +do + java utils.dbping ORACLE_THIN "sys as sysdba" ${sysPassword} ${connectString} > dbping.err 2>&1 + [[ $? == 0 ]] && break; + ((counter++)) + echo "[$counter/${max}] Retrying the DB Connection ..." + sleep 10 +done + +if [ $counter -gt ${max} ]; then + echo "Error output from 'java utils.dbping ORACLE_THIN \"sys as sysdba\" SYSPASSWORD ${connectString}' from '$(pwd)/dbping.err':" + cat dbping.err + echo "[ERROR] Oracle DB Service is not ready after [${max}] iterations ..." + exit -1 +else + java utils.dbping ORACLE_THIN "sys as sysdba" ${sysPassword} ${connectString} +fi + +if [ $customVariables != "none" ]; then + extVariables="-variables $customVariables" +else + extVariables="" +fi +case $rcuType in + +wcp) + extComponents="-component WEBCENTER -component ACTIVITIES" + echo "Creating RCU Schema for OracleWebCenterPortal Domain ..." + ;; +wcpp) + extComponents="-component WEBCENTER -component PORTLET -component ACTIVITIES" + echo "Creating RCU Schema for OracleWebCenterPortal Domain ..." + ;; + * ) + echo "[ERROR] Unknown RCU Schema Type [$rcuType]" + echo "Supported values: wcp,wcpp" + exit -1 + ;; +esac + +echo "Extra RCU Schema Component Choosen[${extComponents}]" +echo "Extra RCU Schema Variable Choosen[${extVariables}]" + +#Debug +#export DISPLAY=0.0 +#/u01/oracle/oracle_common/bin/rcu -listComponents + +/u01/oracle/oracle_common/bin/rcu -silent -createRepository \ + -databaseType ORACLE -connectString ${connectString} \ + -dbUser sys -dbRole sysdba -useSamePasswordForAllSchemaUsers true \ + -selectDependentsForComponents true \ + -schemaPrefix ${schemaPrefix} ${extComponents} ${extVariables} \ + -component MDS -component IAU -component IAU_APPEND -component IAU_VIEWER \ + -component OPSS -component WLS -component STB < /u01/oracle/pwd.txt + diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/dropRepository.sh b/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/dropRepository.sh new file mode 100644 index 000000000..52b6b618c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/dropRepository.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +. /u01/oracle/wlserver/server/bin/setWLSEnv.sh + +echo "Check if the DB Service is ready to accept request " +connectString=${1:-oracle-db.default.svc.cluster.local:1521/devpdb.k8s} +schemaPrefix=${2:-wcp-domain} +rcuType=${3:-wcp} +sysPassword=${4:-Oradoc_db1} +customVariables=${5:-none} + +echo "DB Connection String [$connectString] schemaPrefix [${schemaPrefix}] rcuType[${rcuType}] customVariables[${customVariables}]" + +max=20 +counter=0 +while [ $counter -le ${max} ] +do + java utils.dbping ORACLE_THIN "sys as sysdba" ${sysPassword} ${connectString} > dbping.err 2>&1 + [[ $? == 0 ]] && break; + ((counter++)) + echo "[$counter/${max}] Retrying the DB Connection ..." + sleep 10 +done + +if [ $counter -gt ${max} ]; then + echo "[ERROR] Oracle DB Service is not ready after [${max}] iterations ..." + exit -1 +else + java utils.dbping ORACLE_THIN "sys as sysdba" ${sysPassword} ${connectString} +fi + +if [ $customVariables != "none" ]; then + extVariables="-variables $customVariables" +else + extVariables="" +fi + +case $rcuType in +wcp) + extComponents="-component WEBCENTER -component ACTIVITIES" + echo "Dropping RCU Schema for OracleWebCenterPortal Domain ..." + ;; +wcpp) + extComponents="-component WEBCENTER -component PORTLET -component ACTIVITIES" + echo "Dropping RCU Schema for OracleWebCenterPortal Domain ..." + ;; + * ) + echo "[ERROR] Unknown RCU Schema Type [$rcuType]" + echo "Supported values: wcp,wcpp" + exit -1 + ;; +esac + +echo "Extra RCU Schema Component(s) Choosen[${extComponents}]" +echo "Extra RCU Schema Variable(s) Choosen[${extVariables}]" + +/u01/oracle/oracle_common/bin/rcu -silent -dropRepository \ + -databaseType ORACLE -connectString ${connectString} \ + -dbUser sys -dbRole sysdba \ + -selectDependentsForComponents true \ + -schemaPrefix ${schemaPrefix} ${extComponents} ${extVariables} \ + -component MDS -component IAU -component IAU_APPEND -component IAU_VIEWER \ + -component OPSS -component WLS -component STB < /u01/oracle/pwd.txt + diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/rcu.yaml b/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/rcu.yaml new file mode 100644 index 000000000..e292646b9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/rcu.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Pod +metadata: + labels: + run: rcu + name: rcu + namespace: default +spec: + containers: + - args: + - sleep + - infinity + image: oracle/wcportal:12.2.1.4 + imagePullPolicy: IfNotPresent + name: rcu + imagePullSecrets: + - name: docker-store diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/template/rcu.yaml.template b/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/template/rcu.yaml.template new file mode 100644 index 000000000..b4463793c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-schema/common/template/rcu.yaml.template @@ -0,0 +1,22 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# This is a template for RCU Pod +# +apiVersion: v1 +kind: Pod +metadata: + labels: + run: rcu + name: rcu + namespace: %NAMESPACE% +spec: + containers: + - args: + - sleep + - infinity + image: oracle/wcportal:12.2.1.4 + imagePullPolicy: %WEBLOGIC_IMAGE_PULL_POLICY% + name: rcu + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%imagePullSecrets: + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%- name: %WEBLOGIC_IMAGE_PULL_SECRET_NAME% diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-schema/create-image-pull-secret.sh b/OracleWebCenterPortal/kubernetes/create-rcu-schema/create-image-pull-secret.sh new file mode 100644 index 000000000..abf2dcbf9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-schema/create-image-pull-secret.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Create ImagePullSecret to pull Oracle DB and OracleWebCenterPortal Image + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" + +function usage { + echo "usage: ${script} -u -p -e -s [-h]" + echo " -u Oracle Container Registry User Name (needed)" + echo " -p Oracle Container Registry Password (needed)" + echo " -e email (needed)" + echo " -s Generated Secret (optional) " + echo " (default: docker-store) " + echo " -h Help" + exit $1 +} + +while getopts ":u:p:s:e:" opt; do + case $opt in + u) username="${OPTARG}" + ;; + p) password="${OPTARG}" + ;; + e) email="${OPTARG}" + ;; + s) secert="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${username} ]; then + echo "${script}: -u must be specified." + usage 1 +fi + +if [ -z ${password} ]; then + echo "${script}: -p must be specified." + usage 1 +fi + +if [ -e ${email} ]; then + echo "${script}: -p must be specified." + usage 1 +fi + +if [ -z ${secret} ]; then + secret="docker-store" +fi + +kubectl delete secret/${secret} --ignore-not-found +echo "Creating ImagePullSecret on container-registry.oracle.com" +kubectl create secret docker-registry ${secret} --docker-server=container-registry.oracle.com --docker-username=${username} --docker-password=${password} --docker-email=${email} diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-schema/create-rcu-schema.sh b/OracleWebCenterPortal/kubernetes/create-rcu-schema/create-rcu-schema.sh new file mode 100644 index 000000000..e7ec8023e --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-schema/create-rcu-schema.sh @@ -0,0 +1,204 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Configure RCU schema based on schemaPreifix and rcuDatabaseURL + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/../common/utility.sh + +function usage { + echo "usage: ${script} -s -t -d -i -u -p -n -q -r -o -c [-l] [-h] " + echo " -s RCU Schema Prefix (required)" + echo " -t RCU Schema Type (optional)" + echo " (supported values: wcp,wcpp)" + echo " -d RCU Oracle Database URL (optional) " + echo " (default: oracle-db.default.svc.cluster.local:1521/devpdb.k8s) " + echo " -p OracleWebCenterPortal ImagePullSecret (optional) " + echo " (default: none) " + echo " -i OracleWebCenterPortal Image (optional) " + echo " (default: oracle/wcportal:12.2.1.4) " + echo " -u OracleWebCenterPortal ImagePullPolicy (optional) " + echo " (default: IfNotPresent) " + echo " -n Namespace for RCU pod (optional)" + echo " (default: default)" + echo " -q password for database SYSDBA user. (optional)" + echo " (default: Oradoc_db1)" + echo " -r password for all schema owner (regular user). (optional)" + echo " (default: Oradoc_db1)" + echo " -o Output directory for the generated YAML file. (optional)" + echo " (default: rcuoutput)" + echo " -c Comma-separated custom variables in the format variablename=value. (optional)." + echo " (default: none)" + echo " -l Timeout limit in seconds. (optional)." + echo " (default: 300)" + echo " -h Help" + exit $1 +} + +# Checks if all container(s) in a pod are running state based on READY column using given timeout limit +# NAME READY STATUS RESTARTS AGE +# domain1-adminserver 1/1 Running 0 4m +function checkPodStateUsingCustomTimeout(){ + + status="NotReady" + count=1 + + pod=$1 + ns=$2 + state=${3:-1/1} + timeoutLimit=${4:-300} + max=`expr ${timeoutLimit} / 5` + + echo "Checking Pod READY column for State [$state]" + pname=`kubectl get po -n ${ns} | grep -w ${pod} | awk '{print $1}'` + if [ -z ${pname} ]; then + echo "No such pod [$pod] exists in NameSpace [$ns] " + exit -1 + fi + + rcode=`kubectl get po ${pname} -n ${ns} | grep -w ${pod} | awk '{print $2}'` + [[ ${rcode} -eq "${state}" ]] && status="Ready" + + while [ ${status} != "Ready" -a $count -le $max ] ; do + sleep 5 + rcode=`kubectl get po/$pod -n ${ns} | grep -v NAME | awk '{print $2}'` + [[ ${rcode} -eq "1/1" ]] && status="Ready" + echo "Pod [$1] Status is ${status} Iter [$count/$max]" + count=`expr $count + 1` + done + if [ $count -gt $max ] ; then + echo "[ERROR] Unable to start the Pod [$pod] after 300s "; + exit 1 + fi + + pname=`kubectl get po -n ${ns} | grep -w ${pod} | awk '{print $1}'` + kubectl -n ${ns} get po ${pname} +} + +timeout=300 + +while getopts ":h:s:d:p:i:t:n:q:r:o:u:c:l:" opt; do + case $opt in + s) schemaPrefix="${OPTARG}" + ;; + t) rcuType="${OPTARG}" + ;; + d) dburl="${OPTARG}" + ;; + p) pullsecret="${OPTARG}" + ;; + i) fmwimage="${OPTARG}" + ;; + n) namespace="${OPTARG}" + ;; + q) sysPassword="${OPTARG}" + ;; + r) schemaPassword="${OPTARG}" + ;; + o) rcuOutputDir="${OPTARG}" + ;; + u) imagePullPolicy="${OPTARG}" + ;; + c) customVariables="${OPTARG}" + ;; + l) timeout="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${schemaPrefix} ]; then + echo "${script}: -s must be specified." + usage 1 +fi + +if [ -z ${dburl} ]; then + dburl="oracle-db.default.svc.cluster.local:1521/devpdb.k8s" +fi + +if [ -z ${rcuType} ]; then + rcuType="wcp" +fi + +if [ -z ${pullsecret} ]; then + pullsecret="none" + pullsecretPrefix="#" +fi + +if [ -z ${fmwimage} ]; then + fmwimage="oracle/wcportal:12.2.1.4" +fi + +if [ -z ${imagePullPolicy} ]; then + imagePullPolicy="IfNotPresent" +fi + +if [ -z ${namespace} ]; then + namespace="default" +fi + +if [ -z ${sysPassword} ]; then + sysPassword="Oradoc_db1" +fi + +if [ -z ${schemaPassword} ]; then + schemaPassword="Oradoc_db1" +fi + +if [ -z ${rcuOutputDir} ]; then + rcuOutputDir="rcuoutput" +fi + +if [ -z ${customVariables} ]; then + customVariables="none" +fi + +if [ -z ${timeout} ]; then + timeout=300 +fi + +echo "ImagePullSecret[$pullsecret] Image[${fmwimage}] dburl[${dburl}] rcuType[${rcuType}] customVariables[${customVariables}]" + +mkdir -p ${rcuOutputDir} +rcuYaml=${rcuOutputDir}/rcu.yaml +rm -f ${rcuYaml} +rcuYamlTemp=${scriptDir}/common/template/rcu.yaml.template +cp $rcuYamlTemp $rcuYaml + +# Modify the ImagePullSecret based on input +sed -i -e "s:%NAMESPACE%:${namespace}:g" $rcuYaml +sed -i -e "s:%WEBLOGIC_IMAGE_PULL_POLICY%:${imagePullPolicy}:g" $rcuYaml +sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_NAME%:${pullsecret}:g" $rcuYaml +sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%:${pullsecretPrefix}:g" $rcuYaml +sed -i -e "s?image:.*?image: ${fmwimage}?g" $rcuYaml +kubectl apply -f $rcuYaml + +# Make sure the rcu deployment Pod is RUNNING +checkPod rcu $namespace +checkPodStateUsingCustomTimeout rcu $namespace "1/1" ${timeout} +sleep 5 +kubectl get po/rcu -n $namespace + +# Generate the default password files for rcu command +echo "$sysPassword" > pwd.txt +echo "$schemaPassword" >> pwd.txt + +kubectl exec -n $namespace -i rcu -- bash -c 'cat > /u01/oracle/createRepository.sh' < ${scriptDir}/common/createRepository.sh +kubectl exec -n $namespace -i rcu -- bash -c 'cat > /u01/oracle/pwd.txt' < pwd.txt +rm -rf createRepository.sh pwd.txt + +kubectl exec -n $namespace -i rcu /bin/bash /u01/oracle/createRepository.sh ${dburl} ${schemaPrefix} ${rcuType} ${sysPassword} ${customVariables} +if [ $? != 0 ]; then + echo "######################"; + echo "[ERROR] Could not create the RCU Repository"; + echo "######################"; + exit -3; +fi + +echo "[INFO] Modify the domain.input.yaml to use [$dburl] as rcuDatabaseURL and [${schemaPrefix}] as rcuSchemaPrefix " + diff --git a/OracleWebCenterPortal/kubernetes/create-rcu-schema/drop-rcu-schema.sh b/OracleWebCenterPortal/kubernetes/create-rcu-schema/drop-rcu-schema.sh new file mode 100644 index 000000000..11f8e55fb --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-rcu-schema/drop-rcu-schema.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Drop the RCU schema based on schemaPreifix and Database URL + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/../common/utility.sh + +function usage { + echo "usage: ${script} -s -d -n -q -r -c [-h]" + echo " -s RCU Schema Prefix (required)" + echo " -t RCU Schema Type (optional)" + echo " (supported values: wcp,wcpp) " + echo " -d Oracle Database URL (optional)" + echo " (default: oracle-db.default.svc.cluster.local:1521/devpdb.k8s) " + echo " -n Namespace where RCU pod is deployed (optional)" + echo " (default: default) " + echo " -q password for database SYSDBA user. (optional)" + echo " (default: Oradoc_db1)" + echo " -r password for all schema owner (regular user). (optional)" + echo " (default: Oradoc_db1)" + echo " -c Comma-separated custom variables in the format variablename=value. (optional)." + echo " (default: none)" + echo " -h Help" + exit $1 +} + +while getopts ":h:s:d:t:n:q:r:c:" opt; do + case $opt in + s) schemaPrefix="${OPTARG}" + ;; + t) rcuType="${OPTARG}" + ;; + d) dburl="${OPTARG}" + ;; + n) namespace="${OPTARG}" + ;; + q) sysPassword="${OPTARG}" + ;; + r) schemaPassword="${OPTARG}" + ;; + c) customVariables="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${schemaPrefix} ]; then + echo "${script}: -s must be specified." + usage 1 +fi + +if [ -z ${dburl} ]; then + dburl="oracle-db.default.svc.cluster.local:1521/devpdb.k8s" +fi + +if [ -z ${rcuType} ]; then + rcuType="wcp" +fi + +if [ -z ${namespace} ]; then + namespace="default" +fi + +if [ -z ${sysPassword} ]; then + sysPassword="Oradoc_db1" +fi + +if [ -z ${schemaPassword} ]; then + schemaPassword="Oradoc_db1" +fi + +if [ -z ${customVariables} ]; then + customVariables="none" +fi + +rcupod=`kubectl get po -n ${namespace} | grep rcu | cut -f1 -d " " ` +if [ -z ${rcupod} ]; then + echo "RCU deployment pod not found in [$namespace] Namespace" + exit -2 +fi + +#fmwimage=`kubectl get pod/rcu -o jsonpath="{..image}"` +echo "DB Connection String [$dbUrl], schemaPrefix [${schemaPrefix}] rcuType [${rcuType}] schemaProfileType [${customVariables}]" + +echo "${sysPassword}" > pwd.txt +echo "${schemaPassword}" >> pwd.txt + +kubectl exec -n $namespace -i rcu -- bash -c 'cat > /u01/oracle/dropRepository.sh' < ${scriptDir}/common/dropRepository.sh +kubectl exec -n $namespace -i rcu -- bash -c 'cat > /u01/oracle/pwd.txt' < pwd.txt +rm -rf dropRepository.sh pwd.txt + +kubectl exec -n $namespace -i rcu /bin/bash /u01/oracle/dropRepository.sh ${dburl} ${schemaPrefix} ${rcuType} ${sysPassword} ${customVariables} +if [ $? != 0 ]; then + echo "######################"; + echo "[ERROR] Could not drop the RCU Repository based on dburl[${dburl}] schemaPrefix[${schemaPrefix}] "; + echo "######################"; + exit -3; +fi + +kubectl delete pod rcu -n ${namespace} +checkPodDelete rcu ${namespace} + diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py index 95db06a61..cdd701993 100755 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/common/createWebCenterPortalDomain.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. +# Copyright (c) 2021, 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. import os @@ -17,7 +17,7 @@ class WCPortal12214Provisioner: } MANAGED_SERVERS = [] - + ADDL_MANAGED_SERVERS = [] JRF_12214_TEMPLATES = { 'baseTemplate' : '@@ORACLE_HOME@@/wlserver/common/templates/wls/wls.jar', 'extensionTemplates' : [ @@ -37,7 +37,13 @@ class WCPortal12214Provisioner: ], 'serverGroupsToTarget' : [ 'SPACES-MGD-SVRS', 'AS-MGD-SVRS' ] } - + WCPortlet_12214_TEMPLATES = { + 'extensionTemplates' : [ + '@@ORACLE_HOME@@/wcportal/common/templates/wls/oracle.portlet_producer_apps_template.jar', + '@@ORACLE_HOME@@/wcportal/common/templates/wls/oracle.ootb_producers_template.jar' + ], + 'serverGroupsToTarget' : [ 'PRODUCER_APPS-MGD-SVRS' ] + } def __init__(self, oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName): self.oracleHome = self.validateDirectory(oracleHome) self.javaHome = self.validateDirectory(javaHome) @@ -45,7 +51,7 @@ def __init__(self, oracleHome, javaHome, domainParentDir, adminListenPort, admin return def createWCPortalDomain(self, domainName, user, password, db, dbPrefix, dbPassword, adminListenPort, adminName, - managedNameBase, managedServerPort, prodMode, managedCount, clusterName, sslEnabled, adminServerSSLPort, managedServerSSLPort, + managedNameBase, managedServerPort, prodMode, managedCount, clusterName, sslEnabled, adminServerSSLPort, managedServerSSLPort, configurePortletServer, portletClusterName, portletServerNameBase, portletServerPort, portletServerSSLPort, exposeAdminT3Channel=None, t3ChannelPublicAddress=None, t3ChannelPort=None): print '=================================================================' @@ -55,16 +61,16 @@ def createWCPortalDomain(self, domainName, user, password, db, dbPrefix, dbPassw print 'Creating Base Domain...' domainHome = self.createBaseDomain(domainName, user, password, adminListenPort, adminServerSSLPort, adminName, managedNameBase, - managedServerPort, managedServerSSLPort, prodMode, managedCount, clusterName, sslEnabled) + managedServerPort, managedServerSSLPort, configurePortletServer, portletClusterName, portletServerNameBase, portletServerPort, portletServerSSLPort, prodMode, managedCount, clusterName, sslEnabled) print 'Extending Domain...' - self.extendDomain(domainHome, db, dbPrefix, dbPassword, exposeAdminT3Channel, t3ChannelPublicAddress, + self.extendDomain(domainHome, db, dbPrefix, dbPassword, configurePortletServer, exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) print 'Domain Creation is done...' def createBaseDomain(self, domainName, user, password, adminListenPort, adminServerSSLPort, adminName, - managedNameBase, managedServerPort, managedServerSSLPort, prodMode, managedCount, clusterName ,sslEnabled): + managedNameBase, managedServerPort, managedServerSSLPort, configurePortletServer, portletClusterName, portletServerNameBase, portletServerPort, portletServerSSLPort, prodMode, managedCount, clusterName ,sslEnabled): baseTemplate = self.replaceTokens(self.JRF_12214_TEMPLATES['baseTemplate']) readTemplate(baseTemplate) @@ -81,6 +87,8 @@ def createBaseDomain(self, domainName, user, password, adminListenPort, adminSer ms_count = int(managedCount) ms_sslport = int(managedServerSSLPort) admin_sslport = int(adminServerSSLPort) + portlet_port = int(portletServerPort) + portlet_ssl_port = int(portletServerSSLPort) # Create Admin Server # ======================= print 'Creating Admin Server...' @@ -110,13 +118,19 @@ def createBaseDomain(self, domainName, user, password, adminListenPort, adminSer # ====================== print 'Creating cluster...' cd('/') - cl=create(clusterName, 'Cluster') + cl = create(clusterName, 'Cluster') - # Create managed serversi + # Create managed servers self.MANAGED_SERVERS = self.createManagedServers(ms_count, managedNameBase, ms_port, ms_sslport, clusterName, self.MANAGED_SERVERS, sslEnabled) print 'Managed servers created...' - - # Create Node Manager + if (configurePortletServer == 'true'): + print 'Creating Portlet cluster...' + cd('/') + cl = create(portletClusterName, 'Cluster') + # Create portlet managed server + self.ADDL_MANAGED_SERVERS = self.createManagedServers(ms_count, portletServerNameBase, portlet_port, portlet_ssl_port, portletClusterName, self.ADDL_MANAGED_SERVERS, sslEnabled) + print 'Managed servers created...' + # Create Node Manager # ======================= print 'Creating Node Manager...' for machine in self.MACHINES: @@ -138,7 +152,7 @@ def createBaseDomain(self, domainName, user, password, adminListenPort, adminSer print 'Base domain created at ' + domainHome return domainHome - def extendDomain(self, domainHome, db, dbPrefix, dbPassword, exposeAdminT3Channel, t3ChannelPublicAddress, + def extendDomain(self, domainHome, db, dbPrefix, dbPassword, configurePortletServer, exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort): print 'Extending domain at ' + domainHome print 'Database ' + db @@ -156,20 +170,14 @@ def extendDomain(self, domainHome, db, dbPrefix, dbPassword, exposeAdminT3Channe print 'Applying WCPortal templates...' for extensionTemplate in self.WCPortal_12214_TEMPLATES['extensionTemplates']: addTemplate(self.replaceTokens(extensionTemplate)) - - print 'Extension Templates added...' - cd('/') delete('WC_Portal', 'Server') print 'WC_Portal Managed server deleted...' - self.configureJDBCTemplates(db, dbPrefix, dbPassword) - print 'Targeting Server Groups...' serverGroupsToTarget = list(self.JRF_12214_TEMPLATES['serverGroupsToTarget']) serverGroupsToTarget.extend(self.WCPortal_12214_TEMPLATES['serverGroupsToTarget']) self.targetWCPServers(serverGroupsToTarget) - print 'Targeting Cluster ...' cd('/') @@ -181,6 +189,30 @@ def extendDomain(self, domainHome, db, dbPrefix, dbPassword, exposeAdminT3Channe cd('/CoherenceClusterSystemResource/defaultCoherenceCluster') set('Target', clusterName) + if (configurePortletServer == 'true'): + print 'Applying WCPortlet templates...' + + for extensionTemplate in self.WCPortlet_12214_TEMPLATES['extensionTemplates']: + addTemplate(self.replaceTokens(extensionTemplate)) + print 'WCPortlet Templates added...' + cd('/') + delete('WC_Portlet', 'Server') + print 'WC_Portlet Managed server deleted...' + print 'Targeting Server Groups...' + serverGroupsToTarget = list(self.JRF_12214_TEMPLATES['serverGroupsToTarget']) + serverGroupsToTarget.extend(self.WCPortlet_12214_TEMPLATES['serverGroupsToTarget']) + self.targetWCPortletServers(serverGroupsToTarget) + print 'Targeting Cluster ...' + cd('/') + print "Set CoherenceClusterSystemResource to defaultCoherenceCluster for cluster:" + portletClusterName + cd('/Cluster/' + portletClusterName) + set('CoherenceClusterSystemResource', 'defaultCoherenceCluster') + print "Set WLS clusters as target of defaultCoherenceCluster:" + portletClusterName + cd('/CoherenceClusterSystemResource/defaultCoherenceCluster') + set('Target', portletClusterName) + + print 'Configuring JDBC templates' + self.configureJDBCTemplates(db, dbPrefix, dbPassword) print 'Preparing to update domain...' updateDomain() print 'Domain updated successfully' @@ -225,6 +257,14 @@ def targetWCPServers(self, serverGroupsToTarget): set('CoherenceClusterSystemResource', 'defaultCoherenceCluster') return + def targetWCPortletServers(self, serverGroupsToTarget): + for managedName in self.ADDL_MANAGED_SERVERS: + setServerGroups(managedName, serverGroupsToTarget) + print "Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:" + managedName + cd('/Servers/' + managedName) + set('CoherenceClusterSystemResource', 'defaultCoherenceCluster') + return + def configureJDBCTemplates(self, db, dbPrefix, dbPassword): print 'Configuring the Service Table DataSource...' fmwDb = 'jdbc:oracle:thin:@' + db @@ -379,6 +419,12 @@ def usage(): elif sys.argv[i] == '-managedServerSSLPort': managedServerSSLPort = sys.argv[i + 1] i += 2 + elif sys.argv[i] == '-portletServerPort': + portletServerPort = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-portletServerSSLPort': + portletServerSSLPort = sys.argv[i + 1] + i += 2 elif sys.argv[i] == '-prodMode': prodMode = sys.argv[i + 1] i += 2 @@ -400,6 +446,15 @@ def usage(): elif sys.argv[i] == '-sslEnabled': sslEnabled = sys.argv[i + 1] i += 2 + elif sys.argv[i] == '-portletServerNameBase': + portletServerNameBase = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-portletClusterName': + portletClusterName = sys.argv[i + 1] + i += 2 + elif sys.argv[i] == '-configurePortletServer': + configurePortletServer = sys.argv[i + 1] + i += 2 else: print 'Unexpected argument switch at position ' + str(i) + ': ' + str(sys.argv[i]) usage() @@ -408,4 +463,4 @@ def usage(): provisioner = WCPortal12214Provisioner(oracleHome, javaHome, domainParentDir, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, clusterName) provisioner.createWCPortalDomain(domainName, domainUser, domainPassword, rcuDb, rcuSchemaPrefix, rcuSchemaPassword, adminListenPort, adminName, managedNameBase, managedServerPort, prodMode, managedCount, - clusterName, sslEnabled, adminServerSSLPort, managedServerSSLPort, exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) + clusterName, sslEnabled, adminServerSSLPort, managedServerSSLPort, configurePortletServer, portletClusterName, portletServerNameBase ,portletServerPort, portletServerSSLPort, exposeAdminT3Channel, t3ChannelPublicAddress, t3ChannelPort) diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml index ca3fbbdbb..36d5c49b8 100755 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-inputs.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. +# Copyright (c) 2021, 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. # The version of this inputs file. Do not modify. @@ -7,6 +7,9 @@ version: create-weblogic-sample-domain-inputs-v1 # SSL is disabled by default. Select true to enable SSL. sslEnabled: false +# Include portlet server cluster +configurePortletServer: false + # Port number for admin server adminPort: 7001 @@ -44,8 +47,19 @@ managedServerNameBase: wcpserver managedServerPort: 8888 # SSL Port number for each managed server -managedServerSSLPort: 8889 +managedServerSSLPort: 8788 + +# Portlet cluster name +portletClusterName: wcportlet-cluster + +# Base String to generate portlet server name +portletServerNameBase: wcportletserver +# Port number for each managed server +portletServerPort: 8889 + +# SSL Port number for each managed server +portletServerSSLPort: 8789 # WebCenter Portal Docker image. # To build WebCenter Portal images refer https://oracle.github.io/fmw-kubernetes/wcportal-domains/installguide/prepare-your-environment/#build-oracle-webcenter-portal-image # Update the image according to WebCenter Portal Release version @@ -68,7 +82,7 @@ productionModeEnabled: true # Name of the Kubernetes secret for the Admin Server's username and password # The name must be lowercase. # If not specified, the value is derived from the domainUID as -weblogic-credentials -weblogicCredentialsSecretName: wcpinfra-domain-credentials +weblogicCredentialsSecretName: wcp-domain-domain-credentials # Whether to include server .out to the pod's stdout. # The default is true. @@ -178,7 +192,7 @@ rcuSchemaPrefix: WCP1 rcuDatabaseURL: dbhostname:dbport/servicename # The kubernetes secret containing the database credentials -rcuCredentialsSecret: wcpinfra-rcu-credentials +rcuCredentialsSecret: wcp-domain-rcu-credentials # Provide LoadBalancer Hostname loadBalancerHostName: mycompany.mydomain.com diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-job-template.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-job-template.yaml index a7960ef08..8cfa93ea9 100755 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-job-template.yaml +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain-job-template.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. +# Copyright (c) 2021, 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. apiVersion: batch/v1 kind: Job @@ -81,6 +81,16 @@ spec: value: "%ADMIN_SERVER_SSL_PORT%" - name: MANAGED_SERVER_SSL_PORT value: "%MANAGED_SERVER_SSL_PORT%" + - name: CONFIGURE_PORTLET_SERVER + value: "%CONFIGURE_PORTLET_SERVER%" + - name: PORTLET_SERVER_PORT + value: "%PORTLET_SERVER_PORT%" + - name: PORTLET_SERVER_SSL_PORT + value: "%PORTLET_SERVER_SSL_PORT%" + - name: PORTLET_CLUSTER_NAME + value: "%PORTLET_CLUSTER_NAME%" + - name: PORTLET_SERVER_NAME_BASE + value: "%PORTLET_SERVER_NAME_BASE%" volumes: - name: create-wcp-infra-sample-domain-job-cm-volume configMap: diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain.sh index ebbd5cca5..ecb8eb143 100755 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain.sh +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/create-domain.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright (c) 2021, Oracle and/or its affiliates. +# Copyright (c) 2021, 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. # # Description @@ -23,6 +23,8 @@ script="${BASH_SOURCE[0]}" scriptDir="$( cd "$( dirname "${script}" )" && pwd )" source ${scriptDir}/../../common/utility.sh source ${scriptDir}/../../common/validate.sh +# source WCP specific utility scripts +source ${scriptDir}/../utils/utility.sh function usage { echo usage: ${script} -o dir -i file [-e] [-v] [-t timeout] [-h] @@ -126,7 +128,7 @@ function initialize { validationError "The template file ${deleteJobInput} for deleting a WebLogic domain was not found" fi - dcrInput="${scriptDir}/../../common/jrf-domain-template.yaml" + dcrInput="${scriptDir}/../utils/wcp-domain-template.yaml" if [ ! -f ${dcrInput} ]; then validationError "The template file ${dcrInput} for creating the domain resource was not found" fi @@ -196,7 +198,13 @@ function createDomainHome { CONTAINER_NAME="create-wcp-infra-sample-domain-job" JOB_NAME="${domainUID}-${CONTAINER_NAME}" deleteK8sObj job $JOB_NAME ${createJobOutput} - #Traefik Session Setting + # Traefik Session Setting + + if ( $configurePortletServer == "true" ) ; then + sed -n '/- clusterName:/,/# replicas: /{p}' ${dcrOutput} >> ${dcrOutput} + sed -i "0,/- clusterName: ${clusterName}/s//- clusterName: ${portletClusterName}/" ${dcrOutput} + fi + if [ -z "$loadBalancerType" ] then echo "\$loadBalancerType is empty" @@ -289,4 +297,4 @@ function printSummary { } # Perform the sequence of steps to create a domain -createDomain false +createDomain_WCP false diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/wlst/create-domain-script.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/wlst/create-domain-script.sh index ce12c4e0d..1a7222605 100755 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/wlst/create-domain-script.sh +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/domain-home-on-pv/wlst/create-domain-script.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (c) 2021 Oracle and/or its affiliates. +# Copyright (c) 2021, 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. export DOMAIN_HOME=${DOMAIN_HOME_DIR} @@ -32,4 +32,9 @@ wlst.sh -skipWLSModuleScanning \ -sslEnabled ${SSL_ENABLED} \ -adminServerSSLPort ${ADMIN_SERVER_SSL_PORT} \ -managedServerSSLPort ${MANAGED_SERVER_SSL_PORT} \ + -configurePortletServer ${CONFIGURE_PORTLET_SERVER}\ + -portletServerPort ${PORTLET_SERVER_PORT}\ + -portletServerSSLPort ${PORTLET_SERVER_SSL_PORT}\ + -portletServerNameBase ${PORTLET_SERVER_NAME_BASE}\ + -portletClusterName ${PORTLET_CLUSTER_NAME}\ -t3ChannelPort ${T3_CHANNEL_PORT} diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/utility.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/utility.sh new file mode 100644 index 000000000..61fa27436 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/utility.sh @@ -0,0 +1,390 @@ +#!/usr/bin/env bash +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# Function to generate the properties and yaml files for creating a domain +# +function createFiles_WCP { + + update=false + if [ "$#" == 1 ]; then + echo Trying to update the domain + update=true + fi + + # Make sure the output directory has a copy of the inputs file. + # The user can either pre-create the output directory, put the inputs + # file there, and create the domain from it, or the user can put the + # inputs file some place else and let this script create the output directory + # (if needed) and copy the inputs file there. + echo createFiles - valuesInputFile is ${valuesInputFile} + copyInputsFileToOutputDirectory ${valuesInputFile} "${domainOutputDir}/create-domain-inputs.yaml" + + if [ "${domainHomeInImage}" == "true" ]; then + if [ -z "${domainHomeImageBase}" ]; then + fail "Please specify domainHomeImageBase in your input YAML" + fi + else + if [ -z "${image}" ]; then + fail "Please specify image in your input YAML" + fi + fi + + dcrOutput="${domainOutputDir}/domain.yaml" + + domainName=${domainUID} + + enabledPrefix="" # uncomment the feature + disabledPrefix="# " # comment out the feature + + exposeAnyChannelPrefix="${disabledPrefix}" + if [ "${exposeAdminT3Channel}" = true ]; then + exposeAdminT3ChannelPrefix="${enabledPrefix}" + exposeAnyChannelPrefix="${enabledPrefix}" + # set t3PublicAddress if not set + if [ -z "${t3PublicAddress}" ]; then + getKubernetesClusterIP + t3PublicAddress="${K8S_IP}" + fi + else + exposeAdminT3ChannelPrefix="${disabledPrefix}" + fi + + if [ "${exposeAdminNodePort}" = true ]; then + exposeAdminNodePortPrefix="${enabledPrefix}" + exposeAnyChannelPrefix="${enabledPrefix}" + else + exposeAdminNodePortPrefix="${disabledPrefix}" + fi + + if [ "${istioEnabled}" == "true" ]; then + istioPrefix="${enabledPrefix}" + else + istioPrefix="${disabledPrefix}" + fi + + # The FromModel, MII (model-in-image), and WDT_DOMAIN_TYPE updates in this script + # must remain even though they are not referenced by a sample. They're used by the + # Operator integration test code. If you're interested in MII, + # see './kubernetes/samples/scripts/create-weblogic-domain/model-in-image'. + + # MII settings are used for model-in-image integration testing + if [ "${domainHomeSourceType}" == "FromModel" ]; then + miiPrefix="${enabledPrefix}" + else + miiPrefix="${disabledPrefix}" + fi + + # MII settings are used for model-in-image integration testing + if [ -z "${miiConfigMap}" ]; then + miiConfigMapPrefix="${disabledPrefix}" + else + miiConfigMapPrefix="${enabledPrefix}" + fi + + # For some parameters, use the default value if not defined. + if [ -z "${domainPVMountPath}" ]; then + domainPVMountPath="/shared" + fi + + if [ -z "${logHome}" ]; then + logHome="${domainPVMountPath}/logs/${domainUID}" + fi + + if [ -z "${httpAccessLogInLogHome}" ]; then + httpAccessLogInLogHome="true" + fi + + if [ -z "${dataHome}" ]; then + dataHome="" + fi + + if [ -z "${persistentVolumeClaimName}" ]; then + persistentVolumeClaimName="${domainUID}-weblogic-sample-pvc" + fi + + if [ -z "${weblogicCredentialsSecretName}" ]; then + weblogicCredentialsSecretName="${domainUID}-weblogic-credentials" + fi + + if [ "${domainHomeInImage}" == "true" ]; then + domainPropertiesOutput="${domainOutputDir}/domain.properties" + domainHome="${domainHome:-/u01/oracle/user_projects/domains/${domainName}}" + + # Generate the properties file that will be used when creating the weblogic domain + echo Generating ${domainPropertiesOutput} from ${domainPropertiesInput} + + cp ${domainPropertiesInput} ${domainPropertiesOutput} + sed -i -e "s:%DOMAIN_NAME%:${domainName}:g" ${domainPropertiesOutput} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_PORT%:${adminPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_SERVER_SSL_PORT%:${adminServerSSLPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_SERVER_NAME%:${adminServerName}:g" ${domainPropertiesOutput} + sed -i -e "s:%MANAGED_SERVER_PORT%:${managedServerPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%MANAGED_SERVER_SSL_PORT%:${managedServerSSLPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%MANAGED_SERVER_NAME_BASE%:${managedServerNameBase}:g" ${domainPropertiesOutput} + sed -i -e "s:%CONFIGURED_MANAGED_SERVER_COUNT%:${configuredManagedServerCount}:g" ${domainPropertiesOutput} + sed -i -e "s:%CLUSTER_NAME%:${clusterName}:g" ${domainPropertiesOutput} + sed -i -e "s:%SSL_ENABLED%:${sslEnabled}:g" ${domainPropertiesOutput} + sed -i -e "s:%PRODUCTION_MODE_ENABLED%:${productionModeEnabled}:g" ${domainPropertiesOutput} + sed -i -e "s:%CLUSTER_TYPE%:${clusterType}:g" ${domainPropertiesOutput} + sed -i -e "s;%JAVA_OPTIONS%;${javaOptions};g" ${domainPropertiesOutput} + sed -i -e "s:%T3_CHANNEL_PORT%:${t3ChannelPort}:g" ${domainPropertiesOutput} + sed -i -e "s:%T3_PUBLIC_ADDRESS%:${t3PublicAddress}:g" ${domainPropertiesOutput} + sed -i -e "s:%EXPOSE_T3_CHANNEL%:${exposeAdminT3Channel}:g" ${domainPropertiesOutput} + sed -i -e "s:%FMW_DOMAIN_TYPE%:${fmwDomainType}:g" ${domainPropertiesOutput} + sed -i -e "s:%WDT_DOMAIN_TYPE%:${wdtDomainType}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_USER_NAME%:${username}:g" ${domainPropertiesOutput} + sed -i -e "s:%ADMIN_USER_PASS%:${password}:g" ${domainPropertiesOutput} + sed -i -e "s:%RCU_SCHEMA_PREFIX%:${rcuSchemaPrefix}:g" ${domainPropertiesOutput} + sed -i -e "s:%RCU_SCHEMA_PASSWORD%:${rcuSchemaPassword}:g" ${domainPropertiesOutput} + sed -i -e "s|%RCU_DB_CONN_STRING%|${rcuDatabaseURL}|g" ${domainPropertiesOutput} + + if [ -z "${image}" ]; then + # calculate the internal name to tag the generated image + defaultImageName="domain-home-in-image" + baseTag=${domainHomeImageBase#*:} + defaultImageName=${defaultImageName}:${baseTag:-"latest"} + sed -i -e "s|%IMAGE_NAME%|${defaultImageName}|g" ${domainPropertiesOutput} + export BUILD_IMAGE_TAG=${defaultImageName} + else + sed -i -e "s|%IMAGE_NAME%|${image}|g" ${domainPropertiesOutput} + export BUILD_IMAGE_TAG=${image} + fi + else + # we're in the domain in PV case + + wdtVersion="${WDT_VERSION:-${wdtVersion}}" + httpsProxy="${https_proxy}" + + createJobOutput="${domainOutputDir}/create-domain-job.yaml" + deleteJobOutput="${domainOutputDir}/delete-domain-job.yaml" + + if [ -z "${domainHome}" ]; then + domainHome="${domainPVMountPath}/domains/${domainUID}" + fi + + # Use the default value if not defined. + if [ -z "${createDomainScriptsMountPath}" ]; then + createDomainScriptsMountPath="/u01/weblogic" + fi + + if [ "${update}" == "true" ]; then + createDomainScriptName="update-domain-job.sh" + elif [ -z "${createDomainScriptName}" ]; then + createDomainScriptName="create-domain-job.sh" + fi + echo createDomainScriptName is ${createDomainScriptName} + + # Must escape the ':' value in image for sed to properly parse and replace + image=$(echo ${image} | sed -e "s/\:/\\\:/g") + + # Generate the yaml to create the kubernetes job that will create the weblogic domain + echo Generating ${createJobOutput} + + cp ${createJobInput} ${createJobOutput} + sed -i -e "s:%NAMESPACE%:$namespace:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_CREDENTIALS_SECRET_NAME%:${weblogicCredentialsSecretName}:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE%:${image}:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_POLICY%:${imagePullPolicy}:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_NAME%:${imagePullSecretName}:g" ${createJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%:${imagePullSecretPrefix}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_UID%:${domainUID}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_NAME%:${domainName}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${createJobOutput} + sed -i -e "s:%SSL_ENABLED%:${sslEnabled}:g" ${createJobOutput} + sed -i -e "s:%PRODUCTION_MODE_ENABLED%:${productionModeEnabled}:g" ${createJobOutput} + sed -i -e "s:%ADMIN_SERVER_NAME%:${adminServerName}:g" ${createJobOutput} + sed -i -e "s:%ADMIN_SERVER_NAME_SVC%:${adminServerNameSVC}:g" ${createJobOutput} + sed -i -e "s:%ADMIN_PORT%:${adminPort}:g" ${createJobOutput} + sed -i -e "s:%ADMIN_SERVER_SSL_PORT%:${adminServerSSLPort}:g" ${createJobOutput} + sed -i -e "s:%CONFIGURED_MANAGED_SERVER_COUNT%:${configuredManagedServerCount}:g" ${createJobOutput} + sed -i -e "s:%MANAGED_SERVER_NAME_BASE%:${managedServerNameBase}:g" ${createJobOutput} + sed -i -e "s:%MANAGED_SERVER_NAME_BASE_SVC%:${managedServerNameBaseSVC}:g" ${createJobOutput} + sed -i -e "s:%MANAGED_SERVER_PORT%:${managedServerPort}:g" ${createJobOutput} + sed -i -e "s:%MANAGED_SERVER_SSL_PORT%:${managedServerSSLPort}:g" ${createJobOutput} + sed -i -e "s:%T3_CHANNEL_PORT%:${t3ChannelPort}:g" ${createJobOutput} + sed -i -e "s:%T3_PUBLIC_ADDRESS%:${t3PublicAddress}:g" ${createJobOutput} + sed -i -e "s:%CLUSTER_NAME%:${clusterName}:g" ${createJobOutput} + sed -i -e "s:%CLUSTER_TYPE%:${clusterType}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_PVC_NAME%:${persistentVolumeClaimName}:g" ${createJobOutput} + sed -i -e "s:%DOMAIN_ROOT_DIR%:${domainPVMountPath}:g" ${createJobOutput} + sed -i -e "s:%CREATE_DOMAIN_SCRIPT_DIR%:${createDomainScriptsMountPath}:g" ${createJobOutput} + sed -i -e "s:%CREATE_DOMAIN_SCRIPT%:${createDomainScriptName}:g" ${createJobOutput} + # extra entries for FMW Infra domains + sed -i -e "s:%RCU_CREDENTIALS_SECRET_NAME%:${rcuCredentialsSecret}:g" ${createJobOutput} + sed -i -e "s:%CUSTOM_RCUPREFIX%:${rcuSchemaPrefix}:g" ${createJobOutput} + sed -i -e "s|%CUSTOM_CONNECTION_STRING%|${rcuDatabaseURL}|g" ${createJobOutput} + sed -i -e "s:%EXPOSE_T3_CHANNEL_PREFIX%:${exposeAdminT3Channel}:g" ${createJobOutput} + sed -i -e "s:%FRONTEND_HOST%:${frontEndHost}:g" ${createJobOutput} + sed -i -e "s:%FRONTEND_PORT%:${frontEndPort}:g" ${createJobOutput} + # entries for Istio + sed -i -e "s:%ISTIO_PREFIX%:${istioPrefix}:g" ${createJobOutput} + sed -i -e "s:%ISTIO_ENABLED%:${istioEnabled}:g" ${createJobOutput} + sed -i -e "s:%ISTIO_READINESS_PORT%:${istioReadinessPort}:g" ${createJobOutput} + sed -i -e "s:%WDT_VERSION%:${wdtVersion}:g" ${createJobOutput} + sed -i -e "s|%DOMAIN_TYPE%|${domain_type}|g" ${createJobOutput} + sed -i -e "s|%PROXY_VAL%|${httpsProxy}|g" ${createJobOutput} + sed -i -e "s:%CONFIGURE_PORTLET_SERVER%:${configurePortletServer}:g" ${createJobOutput} + sed -i -e "s:%PORTLET_SERVER_PORT%:${portletServerPort}:g" ${createJobOutput} + sed -i -e "s:%PORTLET_SERVER_SSL_PORT%:${portletServerSSLPort}:g" ${createJobOutput} + sed -i -e "s:%PORTLET_CLUSTER_NAME%:${portletClusterName}:g" ${createJobOutput} + sed -i -e "s:%PORTLET_SERVER_NAME_BASE%:${portletServerNameBase}:g" ${createJobOutput} + + # Generate the yaml to create the kubernetes job that will delete the weblogic domain_home folder + echo Generating ${deleteJobOutput} + + cp ${deleteJobInput} ${deleteJobOutput} + sed -i -e "s:%NAMESPACE%:$namespace:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE%:${image}:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_POLICY%:${imagePullPolicy}:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_CREDENTIALS_SECRET_NAME%:${weblogicCredentialsSecretName}:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_NAME%:${imagePullSecretName}:g" ${deleteJobOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%:${imagePullSecretPrefix}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_UID%:${domainUID}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_NAME%:${domainName}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_PVC_NAME%:${persistentVolumeClaimName}:g" ${deleteJobOutput} + sed -i -e "s:%DOMAIN_ROOT_DIR%:${domainPVMountPath}:g" ${deleteJobOutput} + fi + + if [ "${domainHomeSourceType}" == "FromModel" ]; then + echo domainHomeSourceType is FromModel + # leave domainHomeSourceType to FromModel + if [ "${logHomeOnPV}" == "true" ]; then + logHomeOnPVPrefix="${enabledPrefix}" + else + logHomeOnPVPrefix="${disabledPrefix}" + fi + elif [ "${domainHomeInImage}" == "true" ]; then + domainHomeSourceType="Image" + if [ "${logHomeOnPV}" == "true" ]; then + logHomeOnPVPrefix="${enabledPrefix}" + else + logHomeOnPVPrefix="${disabledPrefix}" + fi + else + domainHomeSourceType="PersistentVolume" + logHomeOnPVPrefix="${enabledPrefix}" + logHomeOnPV=true + fi + + # Generate the yaml file for creating the domain resource + # We want to use wdt's extractDomainResource.sh to get the domain resource + # for domain on pv use case. For others, generate domain resource here + + if [ "${domainHomeSourceType}" != "PersistentVolume" ] || [ "${wdtDomainType}" != "WLS" ] || + [ "${useWdt}" != true ]; then + echo Generating ${dcrOutput} + + cp ${dcrInput} ${dcrOutput} + sed -i -e "s:%DOMAIN_UID%:${domainUID}:g" ${dcrOutput} + sed -i -e "s:%NAMESPACE%:$namespace:g" ${dcrOutput} + sed -i -e "s:%DOMAIN_HOME%:${domainHome}:g" ${dcrOutput} + sed -i -e "s:%DOMAIN_HOME_SOURCE_TYPE%:${domainHomeSourceType}:g" ${dcrOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_POLICY%:${imagePullPolicy}:g" ${dcrOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%:${imagePullSecretPrefix}:g" ${dcrOutput} + sed -i -e "s:%WEBLOGIC_IMAGE_PULL_SECRET_NAME%:${imagePullSecretName}:g" ${dcrOutput} + sed -i -e "s:%WEBLOGIC_CREDENTIALS_SECRET_NAME%:${weblogicCredentialsSecretName}:g" ${dcrOutput} + sed -i -e "s:%INCLUDE_SERVER_OUT_IN_POD_LOG%:${includeServerOutInPodLog}:g" ${dcrOutput} + sed -i -e "s:%LOG_HOME_ON_PV_PREFIX%:${logHomeOnPVPrefix}:g" ${dcrOutput} + sed -i -e "s:%LOG_HOME_ENABLED%:${logHomeOnPV}:g" ${dcrOutput} + sed -i -e "s:%LOG_HOME%:${logHome}:g" ${dcrOutput} + sed -i -e "s:%HTTP_ACCESS_LOG_IN_LOG_HOME%:${httpAccessLogInLogHome}:g" ${dcrOutput} + sed -i -e "s:%DATA_HOME%:${dataHome}:g" ${dcrOutput} + sed -i -e "s:%SERVER_START_POLICY%:${serverStartPolicy}:g" ${dcrOutput} + sed -i -e "s;%JAVA_OPTIONS%;${javaOptions};g" ${dcrOutput} + sed -i -e "s:%DOMAIN_PVC_NAME%:${persistentVolumeClaimName}:g" ${dcrOutput} + sed -i -e "s:%DOMAIN_ROOT_DIR%:${domainPVMountPath}:g" ${dcrOutput} + + if [ "${istioEnabled}" == "true" ]; then + exposeAdminNodePortPrefix="${disabledPrefix}" + fi + + sed -i -e "s:%EXPOSE_T3_CHANNEL_PREFIX%:${exposeAdminT3ChannelPrefix}:g" ${dcrOutput} + sed -i -e "s:%EXPOSE_ANY_CHANNEL_PREFIX%:${exposeAnyChannelPrefix}:g" ${dcrOutput} + sed -i -e "s:%EXPOSE_ADMIN_PORT_PREFIX%:${exposeAdminNodePortPrefix}:g" ${dcrOutput} + sed -i -e "s:%ADMIN_NODE_PORT%:${adminNodePort}:g" ${dcrOutput} + sed -i -e "s:%CLUSTER_NAME%:${clusterName}:g" ${dcrOutput} + sed -i -e "s:%INITIAL_MANAGED_SERVER_REPLICAS%:${initialManagedServerReplicas}:g" ${dcrOutput} + sed -i -e "s:%ISTIO_PREFIX%:${istioPrefix}:g" ${dcrOutput} + sed -i -e "s:%ISTIO_ENABLED%:${istioEnabled}:g" ${dcrOutput} + sed -i -e "s:%ISTIO_READINESS_PORT%:${istioReadinessPort}:g" ${dcrOutput} + # MII settings are used for model-in-image integration testing + sed -i -e "s:%MII_PREFIX%:${miiPrefix}:g" ${dcrOutput} + sed -i -e "s:%MII_CONFIG_MAP_PREFIX%:${miiConfigMapPrefix}:g" ${dcrOutput} + sed -i -e "s:%MII_CONFIG_MAP%:${miiConfigMap}:g" ${dcrOutput} + sed -i -e "s:%WDT_DOMAIN_TYPE%:${wdtDomainType}:g" ${dcrOutput} + + buildServerPodResources + if [ -z "${serverPodResources}" ]; then + sed -i -e "/%OPTIONAL_SERVERPOD_RESOURCES%/d" ${dcrOutput} + else + if [[ $(uname) -eq "Darwin" ]]; then + serverPodResources=$(echo "${serverPodResources}" | sed -e 's/\\n/%NEWLINE%/g') + sed -i -e "s:%OPTIONAL_SERVERPOD_RESOURCES%:${serverPodResources}:g" ${dcrOutput} + sed -i -e $'s|%NEWLINE%|\\\n|g' ${dcrOutput} + else + sed -i -e "s:%OPTIONAL_SERVERPOD_RESOURCES%:${serverPodResources}:g" ${dcrOutput} + fi + fi + + if [ "${domainHomeInImage}" == "true" ]; then + + # now we know which image to use, update the domain yaml file + if [ -z $image ]; then + sed -i -e "s|%WEBLOGIC_IMAGE%|${defaultImageName}|g" ${dcrOutput} + else + sed -i -e "s|%WEBLOGIC_IMAGE%|${image}|g" ${dcrOutput} + fi + else + sed -i -e "s:%WEBLOGIC_IMAGE%:${image}:g" ${dcrOutput} + fi + fi + + # Remove any "...yaml-e" and "...properties-e" files left over from running sed + rm -f ${domainOutputDir}/*.yaml-e + rm -f ${domainOutputDir}/*.properties-e + +} + +# +# Function to create a domain +# $1 - boolean value indicating the location of the domain home +# true means domain home in image +# false means domain home on PV +# +function createDomain_WCP { + if [ "$#" != 1 ]; then + fail "The function must be called with domainHomeInImage parameter." + fi + + domainHomeInImage="${1}" + if [ "true" != "${domainHomeInImage}" ] && [ "false" != "${domainHomeInImage}" ]; then + fail "The value of domainHomeInImage must be true or false: ${domainHomeInImage}" + fi + + # Setup the environment for running this script and perform initial validation checks + initialize + + # Generate files for creating the domain + createFiles_WCP + + # Check that the domain secret exists and contains the required elements + validateDomainSecret + + # Validate the domain's persistent volume claim + if [ "${doValidation}" == true ] && [ "${domainHomeInImage}" == false -o "${logHomeOnPV}" == true ]; then + validateDomainPVC + fi + + # Create the WebLogic domain home + createDomainHome + + if [ "${executeIt}" = true ]; then + createDomainResource + fi + + # Print a summary + printSummary +} diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/wcp-domain-template.yaml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/wcp-domain-template.yaml new file mode 100644 index 000000000..7988e8f53 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/wcp-domain-template.yaml @@ -0,0 +1,123 @@ +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# This is an example of how to define a Domain resource. +# +apiVersion: "weblogic.oracle/v8" +kind: Domain +metadata: + name: %DOMAIN_UID% + namespace: %NAMESPACE% + labels: + weblogic.domainUID: %DOMAIN_UID% +spec: + # The WebLogic Domain Home + domainHome: %DOMAIN_HOME% + + # The domain home source type + # Set to PersistentVolume for domain-in-pv, Image for domain-in-image, or FromModel for model-in-image + domainHomeSourceType: %DOMAIN_HOME_SOURCE_TYPE% + + # The WebLogic Server image that the Operator uses to start the domain + image: "%WEBLOGIC_IMAGE%" + + # imagePullPolicy defaults to "Always" if image version is :latest + imagePullPolicy: "%WEBLOGIC_IMAGE_PULL_POLICY%" + + # Identify which Secret contains the credentials for pulling an image + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%imagePullSecrets: + %WEBLOGIC_IMAGE_PULL_SECRET_PREFIX%- name: %WEBLOGIC_IMAGE_PULL_SECRET_NAME% + + # Identify which Secret contains the WebLogic Admin credentials (note that there is an example of + # how to create that Secret at the end of this file) + webLogicCredentialsSecret: + name: %WEBLOGIC_CREDENTIALS_SECRET_NAME% + + # Whether to include the server out file into the pod's stdout, default is true + includeServerOutInPodLog: %INCLUDE_SERVER_OUT_IN_POD_LOG% + + # Whether to enable log home + %LOG_HOME_ON_PV_PREFIX%logHomeEnabled: %LOG_HOME_ENABLED% + + # Whether to write HTTP access log file to log home + %LOG_HOME_ON_PV_PREFIX%httpAccessLogInLogHome: %HTTP_ACCESS_LOG_IN_LOG_HOME% + + # The in-pod location for domain log, server logs, server out, introspector out, and Node Manager log files + %LOG_HOME_ON_PV_PREFIX%logHome: %LOG_HOME% + # An (optional) in-pod location for data storage of default and custom file stores. + # If not specified or the value is either not set or empty (e.g. dataHome: "") then the + # data storage directories are determined from the WebLogic domain home configuration. + dataHome: "%DATA_HOME%" + + # serverStartPolicy legal values are "NEVER", "IF_NEEDED", or "ADMIN_ONLY" + # This determines which WebLogic Servers the Operator will start up when it discovers this Domain + # - "NEVER" will not start any server in the domain + # - "ADMIN_ONLY" will start up only the administration server (no managed servers will be started) + # - "IF_NEEDED" will start all non-clustered servers, including the administration server and clustered servers up to the replica count + serverStartPolicy: "%SERVER_START_POLICY%" + + serverPod: + # an (optional) list of environment variable to be set on the servers + env: + - name: JAVA_OPTIONS + value: "%JAVA_OPTIONS%" + - name: USER_MEM_ARGS + value: "-Djava.security.egd=file:/dev/./urandom -Xms256m -Xmx1024m " + %OPTIONAL_SERVERPOD_RESOURCES% + %LOG_HOME_ON_PV_PREFIX%volumes: + %LOG_HOME_ON_PV_PREFIX%- name: weblogic-domain-storage-volume + %LOG_HOME_ON_PV_PREFIX% persistentVolumeClaim: + %LOG_HOME_ON_PV_PREFIX% claimName: %DOMAIN_PVC_NAME% + %LOG_HOME_ON_PV_PREFIX%volumeMounts: + %LOG_HOME_ON_PV_PREFIX%- mountPath: %DOMAIN_ROOT_DIR% + %LOG_HOME_ON_PV_PREFIX% name: weblogic-domain-storage-volume + + # adminServer is used to configure the desired behavior for starting the administration server. + adminServer: + # serverStartState legal values are "RUNNING" or "ADMIN" + # "RUNNING" means the listed server will be started up to "RUNNING" mode + # "ADMIN" means the listed server will be start up to "ADMIN" mode + serverStartState: "RUNNING" + %EXPOSE_ANY_CHANNEL_PREFIX%adminService: + %EXPOSE_ANY_CHANNEL_PREFIX% channels: + # The Admin Server's NodePort + %EXPOSE_ADMIN_PORT_PREFIX% - channelName: default + %EXPOSE_ADMIN_PORT_PREFIX% nodePort: %ADMIN_NODE_PORT% + # Uncomment to export the T3Channel as a service + %EXPOSE_T3_CHANNEL_PREFIX% - channelName: T3Channel + serverPod: + # an (optional) list of environment variable to be set on the admin servers + env: + - name: USER_MEM_ARGS + value: "-Djava.security.egd=file:/dev/./urandom -Xms512m -Xmx1024m " + + # clusters is used to configure the desired behavior for starting member servers of a cluster. + # If you use this entry, then the rules will be applied to ALL servers that are members of the named clusters. + clusters: + - clusterName: %CLUSTER_NAME% + serverStartState: "RUNNING" + serverPod: + # Instructs Kubernetes scheduler to prefer nodes for new cluster members where there are not + # already members of the same cluster. + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: "weblogic.clusterName" + operator: In + values: + - $(CLUSTER_NAME) + topologyKey: "kubernetes.io/hostname" + replicas: %INITIAL_MANAGED_SERVER_REPLICAS% + # The number of managed servers to start for unlisted clusters + # replicas: 1 + + # Istio + %ISTIO_PREFIX%configuration: + %ISTIO_PREFIX% istio: + %ISTIO_PREFIX% enabled: %ISTIO_ENABLED% + %ISTIO_PREFIX% readinessPort: %ISTIO_READINESS_PORT% + diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_ms.yml b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_ms.yml deleted file mode 100755 index a6e1f113e..000000000 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_ms.yml +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - -metricsNameSnakeCase: true -restPort: 8888 -queries: -- key: name - keyName: location - prefix: wls_server_ - applicationRuntimes: - key: name - keyName: app - componentRuntimes: - prefix: wls_webapp_config_ - type: WebAppComponentRuntime - key: name - values: [deploymentState, contextRoot, sourceInfo, openSessionsHighCount, openSessionsCurrentCount, sessionsOpenedTotalCount, sessionCookieMaxAgeSecs, sessionInvalidationIntervalSecs, sessionTimeoutSecs, singleThreadedServletPoolSize, sessionIDLength, servletReloadCheckSecs, jSPPageCheckSecs] - servlets: - prefix: wls_servlet_ - key: servletName - -- JVMRuntime: - prefix: wls_jvm_ - key: name - -- executeQueueRuntimes: - prefix: wls_socketmuxer_ - key: name - values: [pendingRequestCurrentCount] - -- workManagerRuntimes: - prefix: wls_workmanager_ - key: name - values: [stuckThreadCount, pendingRequests, completedRequests] - -- threadPoolRuntime: - prefix: wls_threadpool_ - key: name - values: [executeThreadTotalCount, queueLength, stuckThreadCount, hoggingThreadCount] - -- JMSRuntime: - key: name - keyName: jmsruntime - prefix: wls_jmsruntime_ - JMSServers: - prefix: wls_jms_ - key: name - keyName: jmsserver - destinations: - prefix: wls_jms_dest_ - key: name - keyName: destination - -- persistentStoreRuntimes: - prefix: wls_persistentstore_ - key: name -- JDBCServiceRuntime: - JDBCDataSourceRuntimeMBeans: - prefix: wls_datasource_ - key: name -- JTARuntime: - prefix: wls_jta_ - key: name diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/get1.1.0.sh b/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/get1.1.0.sh deleted file mode 100755 index 5dccd1a71..000000000 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/get1.1.0.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -# Copyright (c) 2021, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - -curl -L -O https://github.com/oracle/weblogic-monitoring-exporter/releases/download/v1.1.0/wls-exporter.war - -echo "-------------------wls-exporter-ms start-------------------" -tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX) -mkdir -p $tmp_dir/WEB-INF -echo "created $tmp_dir" - -cp config/config_ms.yml $tmp_dir/config.yml -cp config/weblogic.xml $tmp_dir/WEB-INF/weblogic.xml -echo "Copying completed" - -warDir=$PWD -pushd $tmp_dir - -cp $warDir/wls-exporter.war $warDir/wls-exporter-ms.war -echo "in temp dir" -zip $warDir/wls-exporter-ms.war WEB-INF/weblogic.xml -zip $warDir/wls-exporter-ms.war config.yml -echo "wls-exporter-ms.war is ready" -echo "-------------------wls-exporter-ms end-------------------" - -echo "-------------------wls-exporter-as start-------------------" -cp $warDir/config/config_as.yml $tmp_dir/config.yml -echo "Copying completed" -cp $warDir/wls-exporter.war $warDir/wls-exporter-as.war -echo "in temp dir" -zip $warDir/wls-exporter-as.war WEB-INF/weblogic.xml -zip $warDir/wls-exporter-as.war config.yml -echo "wls-exporter-as.war is ready" -echo "-------------------wls-exporter-as end-------------------" -echo "zip completed" -popd -rm -rf $tmp_dir -rm $warDir/wls-exporter.war diff --git a/OracleWebCenterPortal/kubernetes/create-weblogic-domain-credentials/README.md b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-credentials/README.md new file mode 100644 index 000000000..adfa4c097 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-credentials/README.md @@ -0,0 +1,50 @@ +# Creating credentials for a WebLogic domain + +This sample demonstrates how to create a Kubernetes secret containing the +credentials for a WebLogic domain. The operator expects this secret to be +named following the pattern `domainUID-weblogic-credentials`, where `domainUID` +is the unique identifier of the domain. It must be in the same namespace +that the domain will run in. + +To use the sample, run the command: + +``` +$ ./create-weblogic-credentials.sh -u username -p password -d domainUID -n namespace -s secretName +``` + +The parameters are as follows: + +``` + -u user name, must be specified. + -p password, must be specified. + -d domainUID, optional. The default value is wcp-domain. If specified, the secret will be labeled with the domainUID unless the given value is an empty string. + -n namespace, optional. Use the wcpns namespace if not specified. + -s secretName, optional. If not specified, the secret name will be determined based on the domainUID value. +``` + +This creates a `generic` secret containing the user name and password as literal values. + +You can check the secret with the `kubectl get secret` command. An example is shown below, +including the output: + +``` +$ kubectl -n wcpns get secret wcp-domain-weblogic-credentials -o yaml +apiVersion: v1 +data: + password: d2VsY29tZTE= + username: d2VibG9naWM= +kind: Secret +metadata: + creationTimestamp: 2018-12-12T20:25:20Z + labels: + weblogic.domainName: wcp-domain + weblogic.domainUID: wcp-domain + name: wcp-domain-weblogic-credentials + namespace: wcpns + resourceVersion: "5680" + selfLink: /api/v1/namespaces/wcpns/secrets/wcp-domain-weblogic-credentials + uid: 0c2b3510-fe4c-11e8-994d-00001700101d +type: Opaque + +``` + diff --git a/OracleWebCenterPortal/kubernetes/create-weblogic-domain-credentials/create-weblogic-credentials.sh b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-credentials/create-weblogic-credentials.sh new file mode 100644 index 000000000..8780639a5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-credentials/create-weblogic-credentials.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description +# This sample script creates a Kubernetes secret for WebLogic domain admin credentials. +# +# The following pre-requisites must be handled prior to running this script: +# * The kubernetes namespace must already be created +# +# Secret name determination +# 1) secretName - if specified +# 2) wcp-domain-weblogic-credentials - if secretName and domainUID are both not specified. This is the default out-of-the-box. +# 3) -weblogic-credentials - if secretName is not specified, and domainUID is specified. +# 4) weblogic-credentials - if secretName is not specified, and domainUID is specified as "". +# +# The generated secret will be labeled with +# weblogic.domainUID=$domainUID +# and +# weblogic.domainName=$domainUID +# Where the $domainUID is the value of the -d command line option, unless the value supplied is an empty String "" +# + +script="${BASH_SOURCE[0]}" + +# +# Function to exit and print an error message +# $1 - text of message +function fail { + echo [ERROR] $* + exit 1 +} + +# Try to execute kubectl to see whether kubectl is available +function validateKubectlAvailable { + if ! [ -x "$(command -v kubectl)" ]; then + fail "kubectl is not installed" + fi +} + +function usage { + echo usage: ${script} -u username -p password [-d domainUID] [-n namespace] [-s secretName] [-h] + echo " -u username, must be specified." + echo " -p password, must be specified." + echo " -d domainUID, optional. The default value is wcp-domain. If specified, the secret will be labeled with the domainUID unless the given value is an empty string." + echo " -n namespace, optional. Use the wcpns namespace if not specified" + echo " -s secretName, optional. If not specified, the secret name will be determined based on the domainUID value" + echo " -h Help" + exit $1 +} + +# +# Parse the command line options +# +domainUID=wcp-domain +namespace=wcpns +while getopts "hu:p:n:d:s:" opt; do + case $opt in + u) username="${OPTARG}" + ;; + p) password="${OPTARG}" + ;; + n) namespace="${OPTARG}" + ;; + d) domainUID="${OPTARG}" + ;; + s) secretName="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z $secretName ]; then + if [ -z $domainUID ]; then + secretName=weblogic-credentials + else + secretName=$domainUID-weblogic-credentials + fi +fi + +if [ -z ${username} ]; then + echo "${script}: -u must be specified." + missingRequiredOption="true" +fi + +if [ -z ${password} ]; then + echo "${script}: -p must be specified." + missingRequiredOption="true" +fi + +if [ "${missingRequiredOption}" == "true" ]; then + usage 1 +fi + +# check and see if the secret already exists +result=`kubectl get secret ${secretName} -n ${namespace} --ignore-not-found=true | grep ${secretName} | wc | awk ' { print $1; }'` +if [ "${result:=Error}" != "0" ]; then + fail "The secret ${secretName} already exists in namespace ${namespace}." +fi + +# create the secret +kubectl -n $namespace create secret generic $secretName \ + --from-literal=username=$username \ + --from-literal=password=$password + +# label the secret with domainUID if needed +if [ ! -z $domainUID ]; then + kubectl label secret ${secretName} -n $namespace weblogic.domainUID=$domainUID weblogic.domainName=$domainUID +fi + +# Verify the secret exists +SECRET=`kubectl get secret ${secretName} -n ${namespace} | grep ${secretName} | wc | awk ' { print $1; }'` +if [ "${SECRET}" != "1" ]; then + fail "The secret ${secretName} was not found in namespace ${namespace}" +fi + +echo "The secret ${secretName} has been successfully created in the ${namespace} namespace." + diff --git a/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/README.md b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/README.md new file mode 100644 index 000000000..1947691b3 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/README.md @@ -0,0 +1,222 @@ +# Sample persistent volume and persistent volume claim + +The sample scripts demonstrate the creation of a Kubernetes persistent volume (PV) and persistent volume claim (PVC), which can then be used in a domain resource as a persistent storage for the WebLogic domain home or log files. + +A PV and PVC can be shared by multiple WebLogic domains or dedicated to a particular domain. + +## Prerequisites + +Please read the [Persistent Volumes](../../../../site/persistent-volumes.md) guide before proceeding. + +## Using the scripts to create a PV and PVC + +Prior to running the `create-pv-pvc.sh` script, make a copy of the `create-pv-pvc-inputs.yaml` file, and uncomment and explicitly configure the `weblogicDomainStoragePath` property in the inputs file. + +Run the create script, pointing it at your inputs file and an output directory: + +``` +$ ./create-pv-pvc.sh \ + -i create-pv-pvc-inputs.yaml \ + -o /path/to/output-directory +``` + +The `create-pv-pvc.sh` script will create a subdirectory `pv-pvcs` under the given `/path/to/output-directory` directory. By default, the script generates two YAML files, namely `weblogic-sample-pv.yaml` and `weblogic-sample-pvc.yaml`, in the `/path/to/output-directory/pv-pvcs`. These two YAML files can be used to create the Kubernetes resources using the `kubectl create -f` command. + +``` +$ kubectl create -f wcp-domain-domain-pv.yaml +$ kubectl create -f wcp-domain-domain-pvc.yaml + +``` + +As a convenience, the script can optionally create the PV and PVC resources using the `-e` option. + +The usage of the create script is as follows: + +``` +$ sh create-pv-pvc.sh -h +usage: create-pv-pvc.sh -i file -o dir [-e] [-h] + -i Parameter inputs file, must be specified. + -o Output directory for the generated yaml files, must be specified. + -e Also create the Kubernetes objects using the generated yaml files + -h Help +``` + +If you copy the sample scripts to a different location, make sure that you copy everything in the `/kubernetes/samples/scripts` directory together into the target directory, maintaining the original directory hierarchy. + +## Configuration parameters + +The PV and PVC creation inputs can be customized by editing the `create-pv-pvc-inputs.yaml` file. + +| Parameter | Definition | Default | +| --- | --- | --- | +| `domainUID` | ID of the domain resource to which the generated PV and PVC will be dedicated. Leave it empty if the PV and PVC are going to be shared by multiple domains. | no default | +| `namespace` | Kubernetes namespace to create the PVC. | `default` | +| `baseName` | Base name of the PV and PVC. The generated PV and PVC will be `-pv` and `-pvc` respectively. | `weblogic-sample` | +| `weblogicDomainStoragePath` | Physical path of the storage for the PV. When `weblogicDomainStorageType` is set to `HOST_PATH`, this value should be set the to path to the domain storage on the Kubernetes host. When `weblogicDomainStorageType` is set to NFS, then `weblogicDomainStorageNFSServer` should be set to the IP address or name of the DNS server, and this value should be set to the exported path on that server. Note that the path where the domain is mounted in the WebLogic containers is not affected by this setting, that is determined when you create your domain. | no default | +| `weblogicDomainStorageReclaimPolicy` | Kubernetes PVC policy for the persistent storage. The valid values are: `Retain`, `Delete`, and `Recycle`. | `Retain` | +| `weblogicDomainStorageSize` | Total storage allocated for the PVC. | `10Gi` | +| `weblogicDomainStorageType` | Type of storage. Legal values are `NFS` and `HOST_PATH`. If using `NFS`, `weblogicDomainStorageNFSServer` must be specified. | `HOST_PATH` | +| `weblogicDomainStorageNFSServer`| Name or IP address of the NFS server. This setting only applies if `weblogicDomainStorateType` is `NFS`. | no default | + +## Shared versus dedicated PVC + +By default, the `domainUID` is left empty in the inputs file, which means the generated PV and PVC will not be associated with a particular domain, but can be shared by multiple domain resources in the same Kubernetes namespaces as the PV and PVC. + +For the use cases where dedicated PV and PVC are desired for a particular domain, the `domainUID` needs to be set in the `create-pv-pvc-inputs.yaml` file. The presence of a non-empty `domainUID` in the inputs file will cause the generated PV and PVC to be associated with the specified `domainUID`. The association includes that the names of the generated YAML files and the Kubernetes PV and PVC objects are decorated with the `domainUID`, and the PV and PVC objects are also labeled with the `domainUID`. + +## Verify the results + +The create script will verify that the PV and PVC were created, and will report a failure if there was any error. However, it may be desirable to manually verify the PV and PVC, even if just to gain familiarity with the various Kubernetes objects that were created by the script. + +### Generated YAML files with the default inputs + +The content of the generated `wcp-domain-domain-pvc.yaml`: + +``` +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: wcp-domain-domain-pvc + namespace: default + + storageClassName: wcp-domain-domain-storage-class + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Gi +``` + +The content of the generated `wcp-domain-domain-pv.yaml`: +``` +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: PersistentVolume +metadata: + name: wcp-domain-domain-pv + # labels: + # weblogic.domainUID: +spec: + storageClassName: wcp-domain-domain-storage-class + capacity: + storage: 10Gi + accessModes: + - ReadWriteMany + # Valid values are Retain, Delete or Recycle + persistentVolumeReclaimPolicy: Retain + hostPath: + # nfs: + # server: %SAMPLE_STORAGE_NFS_SERVER% + path: "/scratch/k8s_dir" + +``` + +### Generated YAML files for dedicated PV and PVC + +The content of the generated `wcp-domain-domain-pvc.yaml` when `domainUID` is set to `domain1`: + +``` +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: wcp-domain-domain-pvc + namespace: default + labels: + weblogic.domainUID: wcp-domain +spec: + storageClassName: wcp-domain-domain-storage-class + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Gi +``` + +The content of the generated `wcp-domain-domain-pv.yaml` when `domainUID` is set to `domain1`: +``` +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: PersistentVolume +metadata: + name: wcp-domain-domain-pv + labels: + weblogic.domainUID: wcp-domain +spec: + storageClassName: wcp-domain-domain-storage-class + capacity: + storage: 10Gi + accessModes: + - ReadWriteMany + # Valid values are Retain, Delete or Recycle + persistentVolumeReclaimPolicy: Retain + hostPath: + # nfs: + # server: %SAMPLE_STORAGE_NFS_SERVER% + path: "/scratch/k8s_dir" +``` + +### Verify the PV and PVC objects + +You can use this command to verify the persistent volume was created, note that the `Status` field +should have the value `Bound`, indicating the that persistent volume has been claimed: + +``` +$ kubectl describe pv wcp-domain-domain-pv +Name: wcp-domain-domain-pv +Annotations: pv.kubernetes.io/bound-by-controller=yes +StorageClass: wcp-domain-domain-storage-class +Status: Bound +Claim: default/wcp-domain-domain-pvc +Reclaim Policy: Retain +Access Modes: RWX +Capacity: 10Gi +Message: +Source: + Type: HostPath (bare host directory volume) + Path: /scratch/k8s_dir + HostPathType: +Events: + +``` + +You can use this command to verify the persistent volume claim was created: + +``` +$ kubectl describe pvc wcp-domain-domain-pvc +Name: wcp-domain-domain-pvc +Namespace: default +StorageClass: wcp-domain-domain-storage-class +Status: Bound +Volume: wcp-domain-domain-pv +Annotations: pv.kubernetes.io/bind-completed=yes + pv.kubernetes.io/bound-by-controller=yes +Finalizers: [] +Capacity: 10Gi +Access Modes: RWX +Events: + +``` + +## Troubleshooting + +* Message: `[ERROR] The weblogicDomainStoragePath parameter in kubernetes/samples/scripts/create-weblogic-domain-pv-pvc/create-pv-pvc-inputs.yaml is missing, null or empty` +Edit the file and set the value of the field. This value must be a directory that is world writable. +Optionally, follow these steps to tighten permissions on the named directory after you run the sample the first time: + + * Become the root user. + * `ls -nd $value-of-weblogicDomainStoragePath` + * Note the values of the third and fourth field of the output. + * `chown $third-field:$fourth-field $value-of-weblogicDomainStoragePath` + * `chmod 755 $value-of-weblogicDomainStoragePath` + * Return to your normal user ID. + diff --git a/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/create-pv-pvc-inputs.yaml b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/create-pv-pvc-inputs.yaml new file mode 100644 index 000000000..d18959c27 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/create-pv-pvc-inputs.yaml @@ -0,0 +1,44 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# The version of this inputs file. Do not modify. +version: create-wcp-domain-pv-pvc-inputs-v1 + +# The base name of the pv and pvc +baseName: domain + +# Unique ID identifying a domain. +# If left empty, the generated pv can be shared by multiple domains +# This ID must not contain an underscope ("_"), and must be lowercase and unique across all domains in a Kubernetes cluster. +domainUID: wcp-domain + +# Name of the namespace for the persistent volume claim +namespace: wcpns + +# Persistent volume type for the persistent storage. +# The value must be 'HOST_PATH' or 'NFS'. +# If using 'NFS', weblogicDomainStorageNFSServer must be specified. +weblogicDomainStorageType: HOST_PATH + +# The server name or ip address of the NFS server to use for the persistent storage. +# The following line must be uncomment and customized if weblogicDomainStorateType is NFS: +#weblogicDomainStorageNFSServer: nfsServer + +# Physical path of the persistent storage. +# When weblogicDomainStorageType is set to HOST_PATH, this value should be set the to path to the +# domain storage on the Kubernetes host. +# When weblogicDomainStorageType is set to NFS, then weblogicDomainStorageNFSServer should be set +# to the IP address or name of the DNS server, and this value should be set to the exported path +# on that server. +# Note that the path where the domain is mounted in the WebLogic containers is not affected by this +# setting, that is determined when you create your domain. +# The following line must be uncomment and customized: +weblogicDomainStoragePath: /scratch/k8s_dir + +# Reclaim policy of the persistent storage +# The valid values are: 'Retain', 'Delete', and 'Recycle' +weblogicDomainStorageReclaimPolicy: Retain + +# Total storage allocated to the persistent storage. +weblogicDomainStorageSize: 10Gi + diff --git a/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/create-pv-pvc.sh b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/create-pv-pvc.sh new file mode 100644 index 000000000..ba3de3459 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/create-pv-pvc.sh @@ -0,0 +1,267 @@ +#!/usr/bin/env bash +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description +# This sample script generates the Kubernetes yaml files for a persistent volume and persistent volume claim +# that can be used by a domain custom resource. +# +# The creation inputs can be customized by editing create-pv-pvc-inputs.yaml +# +# The following pre-requisites must be handled prior to running this script: +# * The Kubernetes namespace must already be created +# + +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/../common/utility.sh +source ${scriptDir}/../common/validate.sh + +function usage { + echo usage: ${script} -i file -o dir [-e] [-h] + echo " -i Parameter inputs file, must be specified." + echo " -o Output directory for the generated yaml files, must be specified." + echo " -e Also create the Kubernetes objects using the generated yaml files" + echo " -h Help" + exit $1 +} + +# +# Parse the command line options +# +executeIt=false +while getopts "ehi:o:" opt; do + case $opt in + i) valuesInputFile="${OPTARG}" + ;; + o) outputDir="${OPTARG}" + ;; + e) executeIt=true + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${valuesInputFile} ]; then + echo "${script}: -i must be specified." + missingRequiredOption="true" +fi + +if [ -z ${outputDir} ]; then + echo "${script}: -o must be specified." + missingRequiredOption="true" +fi + +if [ "${missingRequiredOption}" == "true" ]; then + usage 1 +fi + +# +# Function to initialize and validate the output directory +# for the generated yaml files for this domain. +# +function initOutputDir { + pvOutputDir="$outputDir/pv-pvcs" + + if [ -z ${domainUID} ]; then + pvOutput="${pvOutputDir}/${baseName}-pv.yaml" + pvcOutput="${pvOutputDir}/${baseName}-pvc.yaml" + persistentVolumeName=${baseName}-pv + persistentVolumeClaimName=${baseName}-pvc + else + pvOutput="${pvOutputDir}/${domainUID}-${baseName}-pv.yaml" + pvcOutput="${pvOutputDir}/${domainUID}-${baseName}-pvc.yaml" + persistentVolumeName=${domainUID}-${baseName}-pv + persistentVolumeClaimName=${domainUID}-${baseName}-pvc + fi + removeFileIfExists ${pvOutputDir}/{valuesInputFile} + removeFileIfExists ${pvOutputDir}/{pvOutput} + removeFileIfExists ${pvOutputDir}/{pvcOutput} + removeFileIfExists ${pvOutputDir}/create-pv-pvc-inputs.yaml +} + +# +# Function to setup the environment to run the create domain job +# +function initialize { + + # Validate the required files exist + validateErrors=false + + if [ -z "${valuesInputFile}" ]; then + validationError "You must use the -i option to specify the name of the inputs parameter file (a modified copy of kubernetes/samples/scripts/create-weblogic-domain-pv-pvc/create-pv-pvc-inputs.yaml)." + else + if [ ! -f ${valuesInputFile} ]; then + validationError "Unable to locate the input parameters file ${valuesInputFile}" + fi + fi + + if [ -z "${outputDir}" ]; then + validationError "You must use the -o option to specify the name of an existing directory to store the generated yaml files in." + fi + + domainPVInput="${scriptDir}/pv-template.yaml" + if [ ! -f ${domainPVInput} ]; then + validationError "The template file ${domainPVInput} for generating a persistent volume was not found" + fi + + domainPVCInput="${scriptDir}/pvc-template.yaml" + if [ ! -f ${domainPVCInput} ]; then + validationError "The template file ${domainPVCInput} for generating a persistent volume claim was not found" + fi + + failIfValidationErrors + + # Parse the commonn inputs file + parseCommonInputs + validateInputParamsSpecified \ + weblogicDomainStoragePath \ + weblogicDomainStorageSize \ + baseName \ + namespace \ + version + + export requiredInputsVersion="create-weblogic-sample-domain-pv-pvc-inputs-v1" + validateDomainUid + validateNamespace + validateWeblogicDomainStorageType + validateWeblogicDomainStorageReclaimPolicy + initOutputDir + failIfValidationErrors +} + + +# +# Function to generate the yaml files for creating a domain +# +function createYamlFiles { + + # Create a directory for this domain's output files + mkdir -p ${pvOutputDir} + + # Make sure the output directory has a copy of the inputs file. + # The user can either pre-create the output directory, put the inputs + # file there, and create the domain from it, or the user can put the + # inputs file some place else and let this script create the output directory + # (if needed) and copy the inputs file there. + copyInputsFileToOutputDirectory ${valuesInputFile} "${pvOutputDir}/create-pv-pvc-inputs.yaml" + + enabledPrefix="" # uncomment the feature + disabledPrefix="# " # comment out the feature + + echo Generating ${pvOutput} + + cp ${domainPVInput} ${pvOutput} + if [ "${weblogicDomainStorageType}" == "NFS" ]; then + hostPathPrefix="${disabledPrefix}" + nfsPrefix="${enabledPrefix}" + sed -i -e "s:%SAMPLE_STORAGE_NFS_SERVER%:${weblogicDomainStorageNFSServer}:g" ${pvOutput} + else + hostPathPrefix="${enabledPrefix}" + nfsPrefix="${disabledPrefix}" + fi + + sed -i -e "s:%NAMESPACE%:$namespace:g" ${pvOutput} + if [ -z ${domainUID} ]; then + domainUIDLabelPrefix="${disabledPrefix}" + separator="" + else + domainUIDLabelPrefix="${enabledPrefix}" + separator="-" + fi + sed -i -e "s:%DOMAIN_UID%:$domainUID:g" ${pvOutput} + sed -i -e "s:%SEPARATOR%:$separator:g" ${pvOutput} + sed -i -e "s:%DOMAIN_UID_LABEL_PREFIX%:${domainUIDLabelPrefix}:g" ${pvOutput} + + sed -i -e "s:%BASE_NAME%:$baseName:g" ${pvOutput} + sed -i -e "s:%SAMPLE_STORAGE_PATH%:${weblogicDomainStoragePath}:g" ${pvOutput} + sed -i -e "s:%SAMPLE_STORAGE_RECLAIM_POLICY%:${weblogicDomainStorageReclaimPolicy}:g" ${pvOutput} + sed -i -e "s:%SAMPLE_STORAGE_SIZE%:${weblogicDomainStorageSize}:g" ${pvOutput} + sed -i -e "s:%HOST_PATH_PREFIX%:${hostPathPrefix}:g" ${pvOutput} + sed -i -e "s:%NFS_PREFIX%:${nfsPrefix}:g" ${pvOutput} + + # Generate the yaml to create the persistent volume claim + echo Generating ${pvcOutput} + + cp ${domainPVCInput} ${pvcOutput} + sed -i -e "s:%NAMESPACE%:$namespace:g" ${pvcOutput} + sed -i -e "s:%BASE_NAME%:${baseName}:g" ${pvcOutput} + + sed -i -e "s:%DOMAIN_UID%:$domainUID:g" ${pvcOutput} + sed -i -e "s:%SEPARATOR%:$separator:g" ${pvcOutput} + sed -i -e "s:%DOMAIN_UID_LABEL_PREFIX%:${domainUIDLabelPrefix}:g" ${pvcOutput} + + sed -i -e "s:%SAMPLE_STORAGE_SIZE%:${weblogicDomainStorageSize}:g" ${pvcOutput} + + # Remove any "...yaml-e" files left over from running sed + rm -f ${pvOutputDir}/*.yaml-e +} + +# +# Function to create the domain's persistent volume +# +function createDomainPV { + # Check if the persistent volume is already available + checkPvExists ${persistentVolumeName} + if [ "${PV_EXISTS}" = "false" ]; then + echo Creating the persistent volume ${persistentVolumeName} + kubectl create -f ${pvOutput} + checkPvState ${persistentVolumeName} Available + fi +} + +# +# Function to create the domain's persistent volume claim +# Must be called after createDomainPV since it relies on +# createDomainPV defining persistentVolumeName +# +function createDomainPVC { + # Check if the persistent volume claim is already available + checkPvcExists ${persistentVolumeClaimName} ${namespace} + if [ "${PVC_EXISTS}" = "false" ]; then + echo Creating the persistent volume claim ${persistentVolumeClaimName} + kubectl create -f ${pvcOutput} + checkPvState ${persistentVolumeName} Bound + fi +} + +# +# Function to output to the console a summary of the work completed +# +function printSummary { + echo "The following files were generated:" + echo " ${pvOutput}" + echo " ${pvcOutput}" +} + +# +# Perform the following sequence of steps to create a domain +# + +# Setup the environment for running this script and perform initial validation checks +initialize + +# Generate the yaml files for creating the domain +createYamlFiles + +# All done if the generate only option is true +if [ "${executeIt}" = true ]; then + + # Create the domain's persistent volume + createDomainPV + + # Create the domain's persistent volume claim + createDomainPVC +fi + +# Output a job summary +printSummary + +echo +echo Completed + + diff --git a/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/pv-template.yaml b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/pv-template.yaml new file mode 100644 index 000000000..49e33a22f --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/pv-template.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: PersistentVolume +metadata: + name: %DOMAIN_UID%%SEPARATOR%%BASE_NAME%-pv + labels: + %DOMAIN_UID_LABEL_PREFIX%weblogic.domainUID: %DOMAIN_UID% +spec: + storageClassName: %DOMAIN_UID%%SEPARATOR%%BASE_NAME%-storage-class + capacity: + storage: %SAMPLE_STORAGE_SIZE% + accessModes: + - ReadWriteMany + # Valid values are Retain, Delete or Recycle + persistentVolumeReclaimPolicy: %SAMPLE_STORAGE_RECLAIM_POLICY% + %HOST_PATH_PREFIX%hostPath: + %NFS_PREFIX%nfs: + %NFS_PREFIX%server: %SAMPLE_STORAGE_NFS_SERVER% + path: "%SAMPLE_STORAGE_PATH%" diff --git a/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/pvc-template.yaml b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/pvc-template.yaml new file mode 100644 index 000000000..49e8d5afb --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/create-weblogic-domain-pv-pvc/pvc-template.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: %DOMAIN_UID%%SEPARATOR%%BASE_NAME%-pvc + namespace: %NAMESPACE% + labels: + %DOMAIN_UID_LABEL_PREFIX%weblogic.domainUID: %DOMAIN_UID% +spec: + storageClassName: %DOMAIN_UID%%SEPARATOR%%BASE_NAME%-storage-class + accessModes: + - ReadWriteMany + resources: + requests: + storage: %SAMPLE_STORAGE_SIZE% diff --git a/OracleWebCenterPortal/kubernetes/delete-domain/README.md b/OracleWebCenterPortal/kubernetes/delete-domain/README.md new file mode 100644 index 000000000..800c7094a --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/delete-domain/README.md @@ -0,0 +1,27 @@ +# Deleting domain resources created while executing the samples + +After running the sample, you will need to release domain resources that +can then be used for other purposes. The script in this sample demonstrates one approach to releasing +domain resources. + +## Using the script to delete domain resources + +```shell +$ ./delete-weblogic-domain-resources.sh \ + -d domain-uid[,domain-uid...] \ + [-s max-seconds] \ + [-t] +``` +The required option `-d` takes `domain-uid` values (separated + by commas and no spaces) to identify the domain resources that should be deleted. + +To limit the amount of time spent on attempting to delete domain resources, use `-s`. +The option must be followed by an integer that represents the total number of seconds +that will be spent attempting to delete resources. The default number of seconds is 120. + +The optional option `-t` shows what the script will delete without executing the deletion. + +To see the help associated with the script: +```shell +$ ./delete-weblogic-domain-resources.sh -h +``` diff --git a/OracleWebCenterPortal/kubernetes/delete-domain/delete-weblogic-domain-resources.sh b/OracleWebCenterPortal/kubernetes/delete-domain/delete-weblogic-domain-resources.sh new file mode 100644 index 000000000..fd54d1ea0 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/delete-domain/delete-weblogic-domain-resources.sh @@ -0,0 +1,283 @@ +#!/bin/bash +# Copyright (c) 2019, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Description: +# Use this script to delete all kubernetes resources associated +# with a set of given domains. Alternatively, run the script +# in a test mode to show what would be deleted without actually +# performing the deletes. +# +# Usage: +# See "function usage" below or call this script with no parameters. +# + +script="${BASH_SOURCE[0]}" + +function usage { +cat << EOF + Usage: + + $(basename $0) -d domain-uid,domain-uid,... [-s max-seconds] [-t] + $(basename $0) -h + + Perform a best-effort delete of the kubernetes resources for + the given domain(s), and retry until either max-seconds is reached + or all resources were deleted (default $default_maxwaitsecs seconds). + + The domains can be specified as a comma-separated list of + domain-uids (no spaces). The domains can be located in any + kubernetes namespace. + + Specify '-t' to run the script in a test mode which will + show kubernetes commands but not actually perform them. + + The script runs in phases: + + Phase 1: Set the serverStartPolicy of each domain to NEVER if + it's not already NEVER. This should cause each + domain's operator to initiate a controlled shutdown + of the domain. Immediately proceed to phase 2. + + Phase 2: Wait up to half of max-seconds for WebLogic + Server pods to exit normally, and then proceed + to phase 3. + + Phase 3: Periodically delete any remaining kubernetes resources + for the specified domains, including any pods + leftover from previous phases. Exit and fail if + max-seconds is exceeded and there are any leftover + kubernetes resources. + + This script exits with a zero status on success, and a + non-zero status on failure. +EOF +} + +# +# getDomainResources domain(s) outfilename +# +# Usage: +# getDomainResources domainA,domainB,... outfilename +# +# Internal helper function +# +# File output is all domain related resources for the given domain uids, one per line, +# in the form: 'kind name [-n namespace]'. For example: +# PersistentVolumeClaim domain1-pv-claim -n default +# PersistentVolume domain1-pv +# +function getDomainResources { + local domain_regex='' + LABEL_SELECTOR="weblogic.domainUID in ($1)" + IFS=',' read -ra UIDS <<< "$1" + for i in "${!UIDS[@]}"; do + if [ $i -gt 0 ]; then + domain_regex="$domain_regex|" + fi + domain_regex="$domain_regex^Domain ${UIDS[$i]} " + done + + # clean the output file + if [ -e $2 ]; then + rm $2 + fi + + # first, let's get all namespaced types with -l $LABEL_SELECTOR + NAMESPACED_TYPES="pod,job,deploy,rs,service,pvc,ingress,cm,serviceaccount,role,rolebinding,secret" + + kubectl get $NAMESPACED_TYPES \ + -l "$LABEL_SELECTOR" \ + -o=jsonpath='{range .items[*]}{.kind}{" "}{.metadata.name}{" -n "}{.metadata.namespace}{"\n"}{end}' \ + --all-namespaces=true >> $2 + + # if domain crd exists, look for domains too: + kubectl get crd domains.weblogic.oracle > /dev/null 2>&1 + if [ $? -eq 0 ]; then + kubectl get domain \ + -o=jsonpath='{range .items[*]}{.kind}{" "}{.metadata.name}{" -n "}{.metadata.namespace}{"\n"}{end}' \ + --all-namespaces=true | egrep "$domain_regex" >> $2 + fi + + # now, get all non-namespaced types with -l $LABEL_SELECTOR + + NOT_NAMESPACED_TYPES="pv,clusterroles,clusterrolebindings" + + kubectl get $NOT_NAMESPACED_TYPES \ + -l "$LABEL_SELECTOR" \ + -o=jsonpath='{range .items[*]}{.kind}{" "}{.metadata.name}{"\n"}{end}' \ + --all-namespaces=true >> $2 +} + +# +# deleteDomains domain(s) maxwaitsecs +# +# Usage: +# deleteDomains domainA,domainB,... maxwaitsecs +# +# Internal helper function +# This function first sets the serverStartPolicy of each Domain to NEVER +# and waits up to half of $2 for pods to 'self delete'. It then performs +# a helm delete on $1, and finally it directly deletes +# any remaining k8s resources for domain $1 (including any remaining pods) +# and retries these direct deletes up to $2 seconds. +# +# If global $test_mode is true, it shows candidate actions but doesn't +# actually perform them +# +function deleteDomains { + + if [ "$test_mode" = "true" ]; then + echo @@ Test mode! Displaying commands for deleting kubernetes resources with label weblogic.domainUID \'$1\' without actually deleting them. + else + echo @@ Deleting kubernetes resources with label weblogic.domainUID \'$1\'. + fi + + local maxwaitsecs=${2:-$default_maxwaitsecs} + local tempfile="/tmp/$(basename $0).tmp.$$" # == /tmp/[script-file-name].tmp.[pid] + local mstart=`date +%s` + local phase=1 + + while : ; do + # get all k8s resources with matching domain-uid labels and put them in $tempfile + getDomainResources $1 $tempfile + + # get a count of all k8s resources with matching domain-uid labels + local allcount=`wc -l $tempfile | awk '{ print $1 }'` + + # get a count of all WLS pods (any pod with a matching domain-uid label that doesn't have 'traefik' or 'apache' embedded in its name) + local podcount=`grep "^Pod" $tempfile | grep -v traefik | grep -v apache | wc -l | awk '{ print $1 }'` + + local mnow=`date +%s` + + echo @@ $allcount resources remaining after $((mnow - mstart)) seconds, including $podcount WebLogic Server pods. Max wait is $maxwaitsecs seconds. + + # Exit if all k8s resources deleted or max wait seconds exceeded. + + if [ $allcount -eq 0 ]; then + echo @@ Success. + rm -f $tempfile + exit 0 + elif [ $((mnow - mstart)) -gt $maxwaitsecs ]; then + echo @@ Error! Max wait of $maxwaitsecs seconds exceeded with $allcount resources remaining, including $podcount WebLogic Server pods. Giving up. Remaining resources: + cat $tempfile + rm -f $tempfile + exit $allcount + fi + + # In phase 1, set the serverStartPolicy of each domain to NEVER and then immediately + # proceed to phase 2. If there are no domains or WLS pods, we also immediately go to phase 2. + + if [ $phase -eq 1 ]; then + phase=2 + if [ $podcount -gt 0 ]; then + echo @@ "Setting serverStartPolicy to NEVER on each domain (this should cause operator(s) to initiate a controlled shutdown of the domain's pods.)" + cat $tempfile | grep "^Domain" | while read line; do + local name="`echo $line | awk '{ print $2 }'`" + local namespace="`echo $line | awk '{ print $4 }'`" + if [ "$test_mode" = "true" ]; then + echo "kubectl patch domain $name -n $namespace -p '{\"spec\":{\"serverStartPolicy\":\"NEVER\"}}' --type merge" + else + kubectl patch domain $name -n $namespace -p '{"spec":{"serverStartPolicy":"NEVER"}}' --type merge + fi + done + fi + fi + + # In phase 2, wait for the WLS pod count to go down to 0 for at most half + # of 'maxwaitsecs'. Otherwise proceed immediately to phase 3. + + if [ $phase -eq 2 ]; then + if [ $podcount -eq 0 ]; then + echo @@ All pods shutdown, about to directly delete remaining resources. + phase=3 + elif [ $((mnow - mstart)) -gt $((maxwaitsecs / 2)) ]; then + echo @@ Warning! $podcount WebLogic Server pods remaining but wait time exceeds half of max wait seconds. About to directly delete all remaining resources, including the leftover pods. + phase=3 + else + echo @@ "Waiting for operator to shutdown pods (will wait for no more than half of max wait seconds before directly deleting them)." + sleep 3 + continue + fi + fi + + # In phase 3, directly delete remaining k8s resources for the given domainUids + # (including any leftover WLS pods from previous phases). + + # for each namespace with leftover resources, try delete them + cat $tempfile | awk '{ print $4 }' | grep -v "^$" | sort -u | while read line; do + if [ "$test_mode" = "true" ]; then + echo kubectl -n $line delete $NAMESPACED_TYPES -l "$LABEL_SELECTOR" + else + kubectl -n $line delete $NAMESPACED_TYPES -l "$LABEL_SELECTOR" + fi + done + + # if there are any non-namespaced types left, try delete them + local no_namespace_count=`grep -c -v " -n " $tempfile` + if [ ! "$no_namespace_count" = "0" ]; then + if [ "$test_mode" = "true" ]; then + echo kubectl delete $NOT_NAMESPACED_TYPES -l "$LABEL_SELECTOR" + else + kubectl delete $NOT_NAMESPACED_TYPES -l "$LABEL_SELECTOR" + fi + fi + + # Delete domains, if any + cat $tempfile | grep "^Domain " | while read line; do + if [ "$test_mode" = "true" ]; then + echo kubectl delete $line + else + kubectl delete $line + fi + done + + sleep 3 + done +} + +# main entry point + +# default when to stop retrying (override via command line) +default_maxwaitsecs=120 + +# optional test mode that lists what would be deleted without +# actually deleting (override via command line) +test_mode=false + +domains="" + +# parse command line options +while getopts ":d:s:th" opt; do + case $opt in + d) domains="${OPTARG}" + ;; + + s) maxwaitsecs="${OPTARG}" + ;; + + t) test_mode="true" + ;; + + h) usage + exit 0 + ;; + + *) usage + exit 9999 + ;; + esac +done + +if [ "$domains" = "" ]; then + usage + exit 9999 +fi + +if [ ! -x "$(command -v kubectl)" ]; then + echo "@@ Error! kubectl is not installed." + exit 9999 +fi + +deleteDomains "${domains}" "${maxwaitsecs:-$default_maxwaitsecs}" + diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/README.md b/OracleWebCenterPortal/kubernetes/domain-lifecycle/README.md new file mode 100644 index 000000000..0eeab95d5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/README.md @@ -0,0 +1,186 @@ +### Domain life cycle sample scripts + +The operator provides sample scripts to start up or shut down a specific Managed Server or cluster in a deployed domain, or the entire deployed domain. + +**Note**: Prior to running these scripts, you must have previously created and deployed the domain. These scripts make use of [jq](https://stedolan.github.io/jq/) for processing JSON. You must have `jq 1.5 or higher` installed in order to run these scripts. See the installation options on the [jq downlod](https://stedolan.github.io/jq/download/) page. + +These scripts can be helpful when scripting the life cycle of a WebLogic Server domain. For information on how to start, stop, restart, and scale WebLogic Server instances in your domain, see [Domain Life Cycle](https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle). + +#### Scripts to start and stop a WebLogic Server +The `startServer.sh` script starts a WebLogic Server in a domain. For clustered Managed Servers, either it increases the `spec.clusters[].replicas` value for the Managed Server's cluster by `1` or updates the `spec.managedServers[].serverStartPolicy` attribute of the domain resource or both as necessary. For the Administration Server, it updates the value of the `spec.adminServer.serverStartPolicy` attribute of the domain resource. For non-clustered Managed Servers, it updates the `spec.managedServers[].serverStartPolicy` attribute of the domain resource. The script provides an option to keep the `spec.clusters[].replicas` value constant for clustered servers. See the script `usage` information by using the `-h` option. + +Use the following command to start the server either by increasing the replica count or by updating the server start policy: +``` +$ startServer.sh -d domain1 -n weblogic-domain-1 -s managed-server1 +[INFO] Updating replica count for cluster 'cluster-1' to 1. +domain.weblogic.oracle/domain1 patched +[INFO] Successfully updated replica count for cluster 'cluster-1' to 1. +``` + +Use the following command to start the server without increasing the replica count: +``` +$ startServer.sh -d domain1 -n weblogic-domain-1 -s managed-server2 -k +[INFO] Patching start policy for 'managed-server2' to 'ALWAYS'. +domain.weblogic.oracle/domain1 patched +[INFO] Successfully patched server 'managed-server2' with 'ALWAYS' start policy. +``` + +The `stopServer.sh` script shuts down a running WebLogic Server in a domain. For clustered Managed Servers, either it decreases the `spec.clusters[].replicas` value for the Managed Server's cluster by `1` or updates the `spec.managedServers[].serverStartPolicy` attribute of the domain resource or both as necessary. For the Administration Server, it updates the value of the `spec.adminServer.serverStartPolicy` attribute of the domain resource. For non-clustered Managed Servers, it updates the `spec.managedServers[].serverStartPolicy` attribute of the domain resource. The script provides an option to keep the `spec.clusters[].replicas` value constant for clustered servers. See the script `usage` information by using the `-h` option. + +Use the following command to stop the server either by decreasing the replica count or by updating the server start policy: +``` +$ stopServer.sh -d domain1 -n weblogic-domain-1 -s managed-server1 +[INFO] Updating replica count for cluster cluster-1 to 0. +domain.weblogic.oracle/domain1 patched +[INFO] Successfully updated replica count for cluster 'cluster-1' to 0. +``` + +Use the following command to stop the server without decreasing the replica count: +``` +$ stopServer.sh -d domain1 -n weblogic-domain-1 -s managed-server2 -k +[INFO] Unsetting the current start policy 'ALWAYS' for 'managed-server2'. +domain.weblogic.oracle/domain1 patched +[INFO] Successfully unset policy 'ALWAYS'. +``` + +### Scripts to start and stop a cluster + +The `startCluster.sh` script starts a cluster by patching the `spec.clusters[].serverStartPolicy` attribute of the domain resource to `IF_NEEDED`. The operator will start the WebLogic Server instance Pods that are part of the cluster after the `serverStartPolicy` attribute is updated to `IF_NEEDED`. See the script `usage` information by using the `-h` option. +``` +$ startCluster.sh -d domain1 -n weblogic-domain-1 -c cluster-1 +[INFO]Patching start policy of cluster 'cluster-1' from 'NEVER' to 'IF_NEEDED'. +domain.weblogic.oracle/domain1 patched +[INFO] Successfully patched cluster 'cluster-1' with 'IF_NEEDED' start policy!. +``` +The `stopCluster.sh` script shuts down a cluster by patching the `spec.clusters[].serverStartPolicy` attribute of the domain resource to `NEVER`. The operator will shut down the WebLogic Server instance Pods that are part of the cluster after the `serverStartPolicy` attribute is updated to `NEVER`. See the script `usage` information by using the `-h` option. +``` +$ stopCluster.sh -d domain1 -n weblogic-domain-1 -c cluster-1 +[INFO] Patching start policy of cluster 'cluster-1' from 'IF_NEEDED' to 'NEVER'. +domain.weblogic.oracle/domain1 patched +[INFO] Successfully patched cluster 'cluster-1' with 'NEVER' start policy! +``` +### Scripts to start and stop a domain +The `startDomain.sh` script starts a deployed domain by patching the `spec.serverStartPolicy` attribute of the domain resource to `IF_NEEDED`. The operator will start the WebLogic Server instance Pods that are part of the domain after the `spec.serverStartPolicy` attribute of the domain resource is updated to `IF_NEEDED`. See the script `usage` information by using the `-h` option. +``` +$ startDomain.sh -d domain1 -n weblogic-domain-1 +[INFO] Patching domain 'domain1' from serverStartPolicy='NEVER' to 'IF_NEEDED'. +domain.weblogic.oracle/domain1 patched +[INFO] Successfully patched domain 'domain1' in namespace 'weblogic-domain-1' with 'IF_NEEDED' start policy! +``` + +The `stopDomain.sh` script shuts down a domain by patching the `spec.serverStartPolicy` attribute of the domain resource to `NEVER`. The operator will shut down the WebLogic Server instance Pods that are part of the domain after the `spec.serverStartPolicy` attribute is updated to `NEVER`. See the script `usage` information by using the `-h` option. +``` +$ stopDomain.sh -d domain1 -n weblogic-domain-1 +[INFO] Patching domain 'domain1' in namespace 'weblogic-domain-1' from serverStartPolicy='IF_NEEDED' to 'NEVER'. +domain.weblogic.oracle/domain1 patched +[INFO] Successfully patched domain 'domain1' in namespace 'weblogic-domain-1' with 'NEVER' start policy! +``` + +### Script to scale a WebLogic cluster + +The `scaleCluster.sh` script scales a WebLogic cluster by patching the `spec.clusters[].replicas` attribute of the domain resource to the specified value. The operator will perform the scaling operation for the WebLogic cluster based on the specified value of the `replicas` attribute after its value is updated. See the script `usage` information by using the `-h` option. +``` +$ scaleCluster.sh -d domain1 -n weblogic-domain-1 -c cluster-1 -r 3 +[2021-02-26T19:04:14.335000Z][INFO] Patching replicas for cluster 'cluster-1' to '3'. +domain.weblogic.oracle/domain1 patched +[2021-02-26T19:04:14.466000Z][INFO] Successfully patched replicas for cluster 'cluster-1'! +``` + +### Script to view the status of a WebLogic cluster + +The `clusterStatus.sh` script can be used to view the status of a WebLogic cluster in the WebLogic domain managed by the operator. The WebLogic Cluster Status contains information about the minimum, maximum, goal, current, and ready replica count for a WebLogic cluster. This script displays a table containing the status for WebLogic clusters in one or more domains across one or more namespaces. See the script `usage` information by using the `-h` option. + +Use the following command to view the status of all WebLogic clusters in all domains across all namespaces. +```shell +$ clusterStatus.sh + +WebLogic Cluster Status -n "" -d "" -c "": + +namespace domain cluster min max goal current ready +--------- ------ ------- --- --- ---- ------- ----- +ns-kvmt mii-domain1 cluster-1 1 5 5 5 5 +weblogic-domain-1 domain1 cluster-1 0 4 2 2 2 +weblogic-domain-1 domain1 cluster-2 0 4 0 0 0 +``` + +Use the following command to view the status of all WebLogic clusters in 'domain1' in 'weblogic-domain-1' namespace. +``` +$ clusterStatus.sh -d domain1 -n weblogic-domain-1 + +WebLogic Cluster Status -n "weblogic-domain-1" -d "domain1" -c "": + +namespace domain cluster min max goal current ready +--------- ------ ------- --- --- ---- ------- ----- +weblogic-domain-1 domain1 cluster-1 0 4 2 2 2 +weblogic-domain-1 domain1 cluster-2 0 4 0 0 0 +``` + +### Scripts to initiate a rolling restart of a WebLogic domain or cluster + +The `rollDomain.sh` script can be used to initiate a rolling restart of the WebLogic Server Pods in a domain managed by the operator. Similarly, the `rollCluster.sh` script can be used to initiate a rolling restart of the WebLogic Server Pods belonging to a WebLogic cluster in a domain managed by the operator. + +The `rollDomain.sh` script updates the value of the `spec.restartVersion` attribute of the domain resource. Then, the operator will do a rolling restart of the Server Pods in the WebLogic domain after the value of the `spec.restartVersion` is updated. You can provide the new value for `spec.restartVersion` as a parameter to the script or the script will automatically generate a new value to trigger the rolling restart. See the script `usage` information by using the `-h` option. + +``` +$ rollDomain.sh -d domain1 -n weblogic-domain-1 +[2021-03-24T04:01:19.733000Z][INFO] Patching restartVersion for domain 'domain1' to '1'. +domain.weblogic.oracle/domain1 patched +[2021-03-24T04:01:19.850000Z][INFO] Successfully patched restartVersion for domain 'domain1'! +``` + +Use the following command to roll the Server Pods in a WebLogic domain with a specific `restartVersion`: +``` +$ rollDomain.sh -r v1 -d domain1 -n weblogic-domain-1 +[2021-03-24T13:43:47.586000Z][INFO] Patching restartVersion for domain 'domain1' to 'v1'. +domain.weblogic.oracle/domain1 patched +[2021-03-24T13:43:47.708000Z][INFO] Successfully patched restartVersion for domain 'domain1'! +``` + +The `rollCluster.sh` script updates the value of the `spec.clusters[].restartVersion` attribute of the domain resource. Then, the operator will do a rolling restart of the WebLogic cluster Server Pods after the value of the `spec.clusters[].restartVersion` is updated. You can provide the new value of the `restartVersion` as a parameter to the script or the script will automatically generate a new value to trigger the rolling restart. See the script `usage` information by using the `-h` option. + +``` +$ rollCluster.sh -c cluster-1 -d domain1 -n weblogic-domain-1 +[2021-03-24T04:03:27.521000Z][INFO] Patching restartVersion for cluster 'cluster-1' to '2'. +domain.weblogic.oracle/domain1 patched +[2021-03-24T04:03:27.669000Z][INFO] Successfully patched restartVersion for cluster 'cluster-1'! +``` + +Use the following command to roll the WebLogic Cluster Servers with a specific `restartVersion`: +``` +$ rollCluster.sh -r v2 -c cluster-1 -d domain1 -n weblogic-domain-1 +[2021-03-24T13:46:16.833000Z][INFO] Patching restartVersion for cluster 'cluster-1' to 'v2'. +domain.weblogic.oracle/domain1 patched +[2021-03-24T13:46:16.975000Z][INFO] Successfully patched restartVersion for cluster 'cluster-1'! +``` + +### Scripts to restart a WebLogic Server in a domain +The `restartServer.sh` script can be used to restart a WebLogic Server in a domain. This script restarts the Server by deleting the Server Pod for the WebLogic Server instance. +``` +$ restartServer.sh -s managed-server1 -d domain1 -n weblogic-domain-1 +[2021-03-24T22:20:22.498000Z][INFO] Initiating restart of 'managed-server1' by deleting server pod 'domain1-managed-server1'. +[2021-03-24T22:20:37.614000Z][INFO] Server restart succeeded ! +``` + +### Scripts to explicitly initiate introspection of a WebLogic domain + +The `introspectDomain.sh` script can be used to rerun a WebLogic domain's introspect job by explicitly initiating the introspection. This script updates the value of the `spec.introspectVersion` attribute of the domain resource. The resulting behavior depends on your domain home source type and other factors, see [Initiating introspection](https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/introspection/#initiating-introspection) for details. You can provide the new value of the `introspectVersion` as a parameter to the script or the script will automatically generate a new value to trigger the introspection. See the script `usage` information by using the `-h` option. + +Use the following command to rerun a domain's introspect job with the `introspectVersion` value generated by the script. +``` +$ introspectDomain.sh -d domain1 -n weblogic-domain-1 +[2021-03-24T21:37:55.989000Z][INFO] Patching introspectVersion for domain 'domain1' to '1'. +domain.weblogic.oracle/domain1 patched +[2021-03-24T21:37:56.110000Z][INFO] Successfully patched introspectVersion for domain 'domain1'! +``` + +Use the following command to rerun a domain's introspect job with a specific `introspectVersion` value. +``` +$ introspectDomain.sh -i v1 -d domain1 -n weblogic-domain-1 +[2021-03-24T21:38:34.369000Z][INFO] Patching introspectVersion for domain 'domain1' to 'v1'. +domain.weblogic.oracle/domain1 patched +[2021-03-24T21:38:34.488000Z][INFO] Successfully patched introspectVersion for domain 'domain1'! +``` + +### Watching the Pods after executing life cycle scripts + +After executing the lifecycle scripts described above for a domain or a cluster or a Server, you can manually run the `kubectl -n MYNS get pods --watch=true --show-labels` command to watch the effect of running the scripts and monitor the status and labels of various Pods. You will need to do 'Ctrl-C' to stop watching the Pods and exit. diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/clusterStatus.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/clusterStatus.sh new file mode 100644 index 000000000..8bfeb45f3 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/clusterStatus.sh @@ -0,0 +1,130 @@ +# !/bin/sh +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +set -eu +set -o pipefail + +function usage() { +cat< ${kubernetesCli} patch domain ${domainUid} \ + -n ${domainNamespace} --type=merge --patch \"${patchJson}\"" + fi + ${kubernetesCli} patch domain ${domainUid} -n ${domainNamespace} --type=merge --patch "${patchJson}" +} + +# timestamp +# purpose: echo timestamp in the form yyyy-mm-ddThh:mm:ss.nnnnnnZ +# example: 2018-10-01T14:00:00.000001Z +function timestamp() { + local timestamp="`date --utc '+%Y-%m-%dT%H:%M:%S.%NZ' 2>&1`" + if [ ! "${timestamp/illegal/xyz}" = "${timestamp}" ]; then + # old shell versions don't support %N or --utc + timestamp="`date -u '+%Y-%m-%dT%H:%M:%S.000000Z' 2>&1`" + fi + echo "${timestamp}" +} + +# +# Function to note that a validate error has occurred +# +function validationError { + printError $* + validateErrors=true +} + +# +# Function to cause the script to fail if there were any validation errors +# +function failIfValidationErrors { + if [ "$validateErrors" = true ]; then + printError 'The errors listed above must be resolved before the script can continue. Please see usage information below.' + usage 1 + fi +} + +# +# Function to lowercase a value and make it a legal DNS1123 name +# $1 - value to convert to DNS legal name +# $2 - return value containing DNS legal name. +function toDNS1123Legal { + local name=$1 + local __result=$2 + local val=`echo "${name}" | tr "[:upper:]" "[:lower:]"` + val=${val//"_"/"-"} + eval $__result="'$val'" +} + diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/introspectDomain.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/introspectDomain.sh new file mode 100644 index 000000000..120eccec7 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/introspectDomain.sh @@ -0,0 +1,105 @@ +# !/bin/sh +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; + +function usage() { + + cat << EOF + + This script initiates introspection of a WebLogic domain by updating + the value of 'spec.introspectVersion' attribute of the domain resource. + + Usage: + + $(basename $0) [-n mynamespace] [-d mydomainuid] [-i introspectVersion] [-m kubecli] + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -i : Introspect version. If this parameter is not provided, + then the script will generate the 'introspectVersion' by + incrementing the existing value. If the 'spec.introspectVersion' + doesn't exist or its value is non-numeric, then the script + will set the 'spec.introspectVersion' value to '1'. + + -m : Kubernetes command line interface. Default is 'kubectl' + if KUBERNETES_CLI env variable is not set. Otherwise + the default is the value of KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +verboseMode=false +patchJson="" +introspectVersion="" + +while getopts "vc:n:m:d:i:h" opt; do + case $opt in + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + i) introspectVersion="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +set -eu + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +# if the introspectVersion is not provided, generate the value of introspectVersion +if [ -z "${introspectVersion}" ]; then + generateDomainIntrospectVersion "${domainJson}" introspectVersion +fi + +printInfo "Patching introspectVersion for domain '${domainUid}' to '${introspectVersion}'." +createPatchJsonToUpdateDomainIntrospectVersion "${introspectVersion}" patchJson + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Successfully patched introspectVersion for domain '${domainUid}'!" diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/restartServer.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/restartServer.sh new file mode 100644 index 000000000..0c7405aba --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/restartServer.sh @@ -0,0 +1,106 @@ +# !/bin/sh +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; +set -eu + +function usage() { + + cat << EOF + + This script restarts a running WebLogic server in a domain by deleting the server pod. + + Usage: + + $(basename $0) -s myserver [-n mynamespace] [-d mydomainuid] [-m kubecli] + + -s : The WebLogic server name (not the pod name). + This parameter is required. + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -m : Kubernetes command line interface. Default is 'kubectl' + if KUBERNETES_CLI env variable is not set. Otherwise the + default is the value of KUBERNETES_CLI env variable. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +serverName="" +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +podName="" +legalDNSPodName="" + +while getopts "s:m:n:d:h" opt; do + case $opt in + s) serverName="${OPTARG}" + ;; + n) domainNamespace="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + # Validate that server name parameter is specified. + if [ -z "${serverName}" ]; then + validationError "Please specify the server name using '-s' parameter e.g. '-s managed-server1'." + fi + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +# Validate that specified server is either part of a cluster or is an independent managed server +validateServerAndFindCluster "${domainUid}" "${domainNamespace}" "${serverName}" isValidServer clusterName isAdminServer +if [ "${isValidServer}" != 'true' ]; then + printError "Server ${serverName} is not part of any cluster and it's not an independent managed server. Please make sure that server name specified is correct." + exit 1 +fi + +podName=${domainUid}-${serverName} +toDNS1123Legal ${podName} legalDNSPodName +printInfo "Initiating restart of '${serverName}' by deleting server pod '${legalDNSPodName}'." +result=$(${kubernetesCli} -n ${domainNamespace} delete pod ${legalDNSPodName} --ignore-not-found) +if [ -z "${result}" ]; then + printError "Server '${serverName}' is not running." +else + printInfo "Server restart succeeded !" +fi diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/rollCluster.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/rollCluster.sh new file mode 100644 index 000000000..858e41706 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/rollCluster.sh @@ -0,0 +1,123 @@ +# !/bin/sh +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; + +function usage() { + + cat << EOF + + This script initiates a rolling restart of the WebLogic cluster server pods in a domain by updating + the value of the 'spec.clusters[].restartVersion' attribute of the domain resource. + + Usage: + + $(basename $0) -c mycluster [-n mynamespace] [-d mydomainuid] [-r restartVersion] [-m kubecli] + + -c : Cluster name (required parameter). + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -r : Restart version. If this parameter is not provided, + then the script will generate the 'restartVersion' + value of the cluster by incrementing the existing + value. If the 'restartVersion' value doesn't exist + for the cluster then it will use the incremented value of + domain 'restartVersion'. If the domain 'restartVersion' also + doesn't exist or effective value is non-numeric, then + the script will set the 'restartVersion' value to '1'. + + -m : Kubernetes command line interface. Default is 'kubectl' + if KUBERNETES_CLI env variable is not set. Otherwise + the default is the value of the KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +verboseMode=false +patchJson="" +restartVersion="" + +while getopts "vc:n:m:d:r:h" opt; do + case $opt in + c) clusterName="${OPTARG}" + ;; + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + r) restartVersion="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +set -eu + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + if [ -z "${clusterName}" ]; then + validationError "Please specify cluster name using '-c' parameter e.g. '-c cluster-1'." + fi + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +isValidCluster="" +validateClusterName "${domainUid}" "${domainNamespace}" "${clusterName}" isValidCluster +if [ "${isValidCluster}" != 'true' ]; then + printError "cluster ${clusterName} is not part of domain ${domainUid} in namespace ${domainNamespace}. Please make sure that cluster name is correct." + exit 1 +fi + +# if the restartVersion is not provided, generate the value of restartVersion +if [ -z "${restartVersion}" ]; then + generateClusterRestartVersion "${domainJson}" "${clusterName}" restartVersion +fi + +printInfo "Patching restartVersion for cluster '${clusterName}' to '${restartVersion}'." +createPatchJsonToUpdateClusterRestartVersion "${domainJson}" "${clusterName}" "${restartVersion}" patchJson + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Successfully patched restartVersion for cluster '${clusterName}'!" diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/rollDomain.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/rollDomain.sh new file mode 100644 index 000000000..4c821d8c8 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/rollDomain.sh @@ -0,0 +1,105 @@ +# !/bin/sh +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; + +function usage() { + + cat << EOF + + This script initiates a rolling restart of pods in a WebLogic domain by updating + the value of the 'spec.restartVersion' attribute of the domain resource. + + Usage: + + $(basename $0) [-n mynamespace] [-d mydomainuid] [-r restartVersion] [-m kubecli] + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -r : Restart version. If this parameter is not provided, + then the script will generate the 'restartVersion' by + incrementing the existing value. If the 'spec.restartVersion' + doesn't exist or its value is non-numeric, then the script + will set the 'spec.restartVersion' value to '1'. + + -m : Kubernetes command line interface. Default is 'kubectl' + if KUBERNETES_CLI env variable is not set. Otherwise + the default is the value of the KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +verboseMode=false +patchJson="" +restartVersion="" + +while getopts "vc:n:m:d:r:h" opt; do + case $opt in + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + r) restartVersion="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +set -eu + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +# if the restartVersion is not provided, generate the value of restartVersion +if [ -z "${restartVersion}" ]; then + generateDomainRestartVersion "${domainJson}" restartVersion +fi + +printInfo "Patching restartVersion for domain '${domainUid}' to '${restartVersion}'." +createPatchJsonToUpdateDomainRestartVersion "${restartVersion}" patchJson + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Successfully patched restartVersion for domain '${domainUid}'!" diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/scaleCluster.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/scaleCluster.sh new file mode 100644 index 000000000..947dd871c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/scaleCluster.sh @@ -0,0 +1,122 @@ +# !/bin/sh +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; + +function usage() { + + cat << EOF + + This script scales a WebLogic cluster in a domain by patching the + 'spec.clusters[].replicas' attribute of the domain + resource. This change will cause the operator to perform a scaling + operation for the WebLogic cluster based on the value of replica count. + + Usage: + + $(basename $0) -c mycluster -r replicas [-n mynamespace] [-d mydomainuid] [-m kubecli] + + -c : Cluster name parameter is required. + + -r : Replica count, parameter is required. + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -m : Kubernetes command line interface. Default is 'kubectl' if KUBERNETES_CLI env + variable is not set. Otherwise default is the value of KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +verboseMode=false +patchJson="" +replicas="" + +while getopts "vc:n:m:d:r:h" opt; do + case $opt in + c) clusterName="${OPTARG}" + ;; + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + r) replicas="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +set -eu + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + if [ -z "${clusterName}" ]; then + validationError "Please specify cluster name using '-c' parameter e.g. '-c cluster-1'." + fi + + if [ -z "${replicas}" ]; then + validationError "Please specify replica count using '-r' parameter e.g. '-r 3'." + fi + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +isValidCluster="" +validateClusterName "${domainUid}" "${domainNamespace}" "${clusterName}" isValidCluster +if [ "${isValidCluster}" != 'true' ]; then + printError "cluster ${clusterName} is not part of domain ${domainUid} in namespace ${domainNamespace}. Please make sure that cluster name is correct." + exit 1 +fi + +isReplicasInAllowedRange "${domainJson}" "${clusterName}" "${replicas}" replicasInAllowedRange range +if [ "${replicasInAllowedRange}" == 'false' ]; then + printError "Replicas value is not in the allowed range of ${range}. Exiting." + exit 1 +fi + +printInfo "Patching replicas for cluster '${clusterName}' to '${replicas}'." +createPatchJsonToUpdateReplicas "${domainJson}" "${clusterName}" "${replicas}" patchJson + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Successfully patched replicas for cluster '${clusterName}'!" diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/startCluster.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/startCluster.sh new file mode 100644 index 000000000..5c8bf034c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/startCluster.sh @@ -0,0 +1,129 @@ +# !/bin/sh +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; + +function usage() { + + cat << EOF + + This script starts a WebLogic cluster in a domain by patching + 'spec.clusters[].serverStartPolicy' attribute of the domain + resource to 'IF_NEEDED'. This change will cause the operator to initiate + startup of cluster's WebLogic server instance pods if the pods are not + already running and the spec.replicas or + 'spec.clusters[].serverStartPolicy' is set higher than zero. + + Usage: + + $(basename $0) -c mycluster [-n mynamespace] [-d mydomainuid] [-m kubecli] + + -c : Cluster name (required parameter). + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -m : Kubernetes command line interface. Default is 'kubectl' if KUBERNETES_CLI env + variable is not set. Otherwise default is the value of KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +set -eu + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +verboseMode=false +patchJson="" + +while getopts "vc:n:m:d:h" opt; do + case $opt in + c) clusterName="${OPTARG}" + ;; + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + if [ -z "${clusterName}" ]; then + validationError "Please specify cluster name using '-c' parameter e.g. '-c cluster-1'." + fi + + failIfValidationErrors + +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +isValidCluster="" +validateClusterName "${domainUid}" "${domainNamespace}" "${clusterName}" isValidCluster +if [ "${isValidCluster}" != 'true' ]; then + printError "cluster ${clusterName} is not part of domain ${domainUid} in namespace ${domainNamespace}. Please make sure that cluster name is correct." + exit 1 +fi + +getDomainPolicy "${domainJson}" domainStartPolicy +# Fail if effective start policy of domain is NEVER or ADMIN_ONLY +if [[ "${domainStartPolicy}" == 'NEVER' || "${domainStartPolicy}" == 'ADMIN_ONLY' ]]; then + printError "Cannot start cluster '${clusterName}', the domain is configured with a 'spec.serverStartPolicy' attribute on the domain resource of 'NEVER' or 'ADMIN_ONLY'." + exit 1 +fi + +# Get server start policy for this cluster +getClusterPolicy "${domainJson}" "${clusterName}" startPolicy +if [ -z "${startPolicy}" ]; then + startPolicy=${domainStartPolicy} +fi + +if [ "${startPolicy}" == 'IF_NEEDED' ]; then + printInfo "No changes needed, exiting. The cluster '${clusterName}' is already started or starting. The effective value of 'spec.clusters[?(clusterName=\"${clusterName}\"].serverStartPolicy' attribute on the domain resource is 'IF_NEEDED'." + exit 0 +fi + +# Set policy value to IF_NEEDED +printInfo "Patching start policy of cluster '${clusterName}' from '${startPolicy}' to 'IF_NEEDED'." +createPatchJsonToUpdateClusterPolicy "${domainJson}" "${clusterName}" "IF_NEEDED" patchJson + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Successfully patched cluster '${clusterName}' with 'IF_NEEDED' start policy!." diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/startDomain.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/startDomain.sh new file mode 100644 index 000000000..fea9cbbe5 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/startDomain.sh @@ -0,0 +1,97 @@ +# !/bin/sh +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh + +function usage() { + + cat << EOF + + This script starts a deployed WebLogic domain by patching 'spec.serverStartPolicy' + attribute of the domain resource to 'IF_NEEDED'. This change will cause the operator + to initiate startup of domain's WebLogic server instance pods if the pods are not + already running. + + Usage: + + $(basename $0) [-n mynamespace] [-d mydomainuid] [-m kubecli] + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -m : Kubernetes command line interface. Default is 'kubectl' if KUBERNETES_CLI env + variable is not set. Otherwise default is the value of KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +verboseMode=false + +while getopts "vn:d:m:h" opt; do + case $opt in + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + + +set -eu +set -o pipefail + +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) + +if [ -z "${domainJson}" ]; then + printError "Domain resource for domain '${domainUid}' not found in namespace '${domainNamespace}'. Exiting." + exit 1 +fi + +getDomainPolicy "${domainJson}" serverStartPolicy + +if [ "${serverStartPolicy}" == 'IF_NEEDED' ]; then + printInfo "No changes needed, exiting. The domain '${domainUid}' is already started or starting. The effective value of 'spec.serverStartPolicy' attribute on the domain resource is 'IF_NEEDED'." + exit 0 +fi + +printInfo "Patching domain '${domainUid}' from serverStartPolicy='${serverStartPolicy}' to 'IF_NEEDED'." + +createPatchJsonToUpdateDomainPolicy "IF_NEEDED" patchJson + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Successfully patched domain '${domainUid}' in namespace '${domainNamespace}' with 'IF_NEEDED' start policy!" diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/startServer.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/startServer.sh new file mode 100644 index 000000000..37b120d71 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/startServer.sh @@ -0,0 +1,242 @@ +# !/bin/sh +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +# This script starts a WebLogic managed server in a domain. +# Internal code notes :- +# - If server start policy is ALWAYS or policy is IF_NEEDED and the server is selected +# to start based on the replica count, it means that server is already started or is +# in the process of starting. In this case, script exits without making any changes. +# +# - If start policy of servers parent cluster or domain is 'NEVER', script +# fails as server can't be started. +# +# - If server is part of a cluster and keep_replica_constant option is false (the default) +# and the effective start policy of the server is IF_NEEDED and increasing replica count +# will naturally start the server, the script increases the replica count. +# +# - If server is part of a cluster and keep_replica_constant option is false (the default) +# and unsetting policy and increasing the replica count will start this server, script +# unsets the policy and increases replica count. For e.g. if replica count is 1 and +# start policy of server2 is NEVER, unsetting policy and increasing replica count will +# start server2. +# +# - If option to keep replica count constant ('-k') is selected and unsetting start policy +# will naturally start the server, script will unset the policy. For e.g. if replica count +# is 2 and start policy of server2 is NEVER, unsetting policy will start server2. +# +# - If above conditions are not true, it implies that either start policy is NEVER or policy +# is IF_NEEDED but server is not next in the order to start. In this case, script sets start +# policy to ALWAYS. For e.g. replica count is 3 and server10 needs to start. The script also +# increments the replica count by default. If option to keep replica count constant ('-k') +# is selected, it only sets the start policy to ALWAYS. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; +set -eu + +function usage() { + + cat << EOF + + This script starts a WebLogic server in a domain. For the managed servers, it either + increases the value of 'spec.clusters[].replicas' by '1' or updates the + 'spec.managedServers[].serverStartPolicy' attribute of the domain + resource or both as necessary for starting the server. For the administration server, it + updates the value of 'spec.adminServer.serverStartPolicy' attribute of the domain resource. + The 'spec.clusters[].replicas' value can be kept constant by using '-k' option. + Please see README.md for more details. + + Usage: + + $(basename $0) -s myserver [-n mynamespace] [-d mydomainuid] [-k] [-m kubecli] [-v] + + -s : The WebLogic server name (not the pod name). + This parameter is required. + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -k : Keep replica count constant for the clustered servers. The default behavior + is to increment the replica count for the clustered servers. This parameter + is ignored for the administration and non-clustered managed servers. + + -m : Kubernetes command line interface. Default is 'kubectl' if KUBERNETES_CLI env + variable is not set. Otherwise default is the value of KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +serverName="" +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +keepReplicaConstant=false +verboseMode=false +withReplicas="CONSTANT" +withPolicy="CONSTANT" +managedServerPolicy="" +effectivePolicy="" +isValidServer="" +patchJson="" +serverStarted="" +startsByPolicyUnset="" +startsByReplicaIncreaseAndPolicyUnset="" +isAdminServer=false + +while getopts "vkd:n:m:s:h" opt; do + case $opt in + s) serverName="${OPTARG}" + ;; + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + k) keepReplicaConstant=true; + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + # Validate the required files exist + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + # Validate that server name parameter is specified. + if [ -z "${serverName}" ]; then + validationError "Please specify a server name using '-s' parameter e.g. '-s managed-server1'." + fi + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +# Validate that specified server is either part of a cluster or is an independent managed server +validateServerAndFindCluster "${domainUid}" "${domainNamespace}" "${serverName}" isValidServer clusterName isAdminServer +if [ "${isValidServer}" != 'true' ]; then + printError "Server ${serverName} is not part of any cluster and it's not an independent managed server. Please make sure that server name specified is correct." + exit 1 +fi + +getClusterPolicy "${domainJson}" "${clusterName}" clusterPolicy +if [ "${clusterPolicy}" == 'NEVER' ]; then + printError "Cannot start server '${serverName}', the server's parent cluster '.spec.clusters[?(clusterName=\"${clusterName}\"].serverStartPolicy' in the domain resource is set to 'NEVER'." + exit 1 +fi + +getDomainPolicy "${domainJson}" domainPolicy +if [ "${domainPolicy}" == 'NEVER' ] || [[ "${domainPolicy}" == 'ADMIN_ONLY' && "${isAdminServer}" != 'true' ]]; then + printError "Cannot start server '${serverName}', the .spec.serverStartPolicy in the domain resource is set to 'NEVER' or 'ADMIN_ONLY'." + exit 1 +fi + +getEffectivePolicy "${domainJson}" "${serverName}" "${clusterName}" effectivePolicy +if [ "${isAdminServer}" == 'true' ]; then + getEffectiveAdminPolicy "${domainJson}" effectivePolicy + if [[ "${effectivePolicy}" == "IF_NEEDED" || "${effectivePolicy}" == "ALWAYS" ]]; then + printInfo "No changes needed, exiting. Server should be already starting or started because effective sever start policy is '${effectivePolicy}'." + exit 0 + fi +fi + +if [ -n "${clusterName}" ]; then + # Server is part of a cluster, check currently started servers + checkStartedServers "${domainJson}" "${serverName}" "${clusterName}" "${withReplicas}" "${withPolicy}" serverStarted + if [[ ${effectivePolicy} == "IF_NEEDED" && ${serverStarted} == "true" ]]; then + printInfo "No changes needed, exiting. The server should be already started or it's in the process of starting. The start policy for server ${serverName} is ${effectivePolicy} and server is chosen to be started based on current replica count." + exit 0 + elif [[ "${effectivePolicy}" == "ALWAYS" && ${serverStarted} == "true" ]]; then + printInfo "No changes needed, exiting. The server should be already started or it's in the process of starting. The start policy for server ${serverName} is ${effectivePolicy}." + exit 0 + fi +else + # Server is an independent managed server. + if [[ "${effectivePolicy}" == "ALWAYS" || "${effectivePolicy}" == "IF_NEEDED" ]]; then + printInfo "No changes needed, exiting. The server should be already started or it's in the process of starting. The start policy for server ${serverName} is ${effectivePolicy}." + exit 0 + fi +fi + +getServerPolicy "${domainJson}" "${serverName}" managedServerPolicy +createServerStartPolicyPatch "${domainJson}" "${serverName}" "ALWAYS" alwaysStartPolicyPatch + +# if server is part of a cluster and replica count will increase +if [[ -n ${clusterName} && "${keepReplicaConstant}" != 'true' ]]; then + #check if server starts by increasing replicas and unsetting policy + withReplicas="INCREASED" + withPolicy="UNSET" + checkStartedServers "${domainJson}" "${serverName}" "${clusterName}" "${withReplicas}" "${withPolicy}" startsByReplicaIncreaseAndPolicyUnset + createReplicaPatch "${domainJson}" "${clusterName}" "INCREMENT" incrementReplicaPatch replicaCount + if [[ -n ${managedServerPolicy} && ${startsByReplicaIncreaseAndPolicyUnset} == "true" ]]; then + # Server starts by increasing replicas and policy unset, increment and unset + printInfo "Unsetting the current start policy '${managedServerPolicy}' for '${serverName}' and incrementing replica count ${replicaCount}." + createPatchJsonToUnsetPolicyAndUpdateReplica "${domainJson}" "${serverName}" "${incrementReplicaPatch}" patchJson + elif [[ -z ${managedServerPolicy} && ${startsByReplicaIncreaseAndPolicyUnset} == "true" ]]; then + # Start policy is not set, server starts by increasing replicas based on effective policy, increment replicas + printInfo "Updating replica count for cluster '${clusterName}' to ${replicaCount}." + createPatchJsonToUpdateReplica "${incrementReplicaPatch}" patchJson + else + # Patch server policy to always and increment replicas + printInfo "Patching start policy of server '${serverName}' from '${effectivePolicy}' to 'ALWAYS' and \ +incrementing replica count for cluster '${clusterName}' to ${replicaCount}." + createPatchJsonToUpdateReplicaAndPolicy "${incrementReplicaPatch}" "${alwaysStartPolicyPatch}" patchJson + fi +elif [[ -n ${clusterName} && "${keepReplicaConstant}" == 'true' ]]; then + # Replica count needs to stay constant, check if server starts by unsetting policy + withReplicas="CONSTANT" + withPolicy="UNSET" + checkStartedServers "${domainJson}" "${serverName}" "${clusterName}" "${withReplicas}" "${withPolicy}" startsByPolicyUnset + if [[ "${effectivePolicy}" == "NEVER" && ${startsByPolicyUnset} == "true" ]]; then + # Server starts by unsetting policy, unset policy + printInfo "Unsetting the current start policy '${effectivePolicy}' for '${serverName}'." + createPatchJsonToUnsetPolicy "${domainJson}" "${serverName}" patchJson + else + # Patch server policy to always + printInfo "Patching start policy for '${serverName}' to 'ALWAYS'." + createPatchJsonToUpdatePolicy "${alwaysStartPolicyPatch}" patchJson + fi +elif [ "${isAdminServer}" == 'true' ]; then + printInfo "Patching start policy of '${serverName}' from '${effectivePolicy}' to 'IF_NEEDED'." + createPatchJsonToUpdateAdminPolicy "${domainJson}" "IF_NEEDED" patchJson +else + # Server is an independent managed server + printInfo "Unsetting the current start policy '${effectivePolicy}' for '${serverName}'." + createPatchJsonToUnsetPolicy "${domainJson}" "${serverName}" patchJson +fi + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Patch command succeeded !" diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopCluster.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopCluster.sh new file mode 100644 index 000000000..6e0410932 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopCluster.sh @@ -0,0 +1,119 @@ +# !/bin/sh +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; + +function usage() { + + cat << EOF + + This script stops a WebLogic cluster in a domain by patching + 'spec.clusters[].serverStartPolicy' attribute of the domain + resource to 'NEVER'. This change will cause the operator to initiate shutdown + of cluster's WebLogic server instance pods if the pods are running. + + Usage: + + $(basename $0) -c mycluster [-n mynamespace] [-d mydomainuid] [-m kubecli] + + -c : Cluster name (required parameter). + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -m : Kubernetes command line interface. Default is 'kubectl' if KUBERNETES_CLI env + variable is not set. Otherwise default is the value of KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +verboseMode=false +patchJson="" + +while getopts "vc:n:m:d:h" opt; do + case $opt in + c) clusterName="${OPTARG}" + ;; + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +set -eu + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + if [ -z "${clusterName}" ]; then + validationError "Please specify cluster name using '-c' parameter e.g. '-c cluster-1'." + fi + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +isValidCluster="" +validateClusterName "${domainUid}" "${domainNamespace}" "${clusterName}" isValidCluster +if [ "${isValidCluster}" != 'true' ]; then + printError "cluster ${clusterName} is not part of domain ${domainUid} in namespace ${domainNamespace}. Please make sure that cluster name is correct." + exit 1 +fi + +# Get server start policy for this server +getClusterPolicy "${domainJson}" "${clusterName}" startPolicy +if [ -z "${startPolicy}" ]; then + getDomainPolicy "${domainJson}" startPolicy +fi + +if [[ "${startPolicy}" == 'NEVER' || "${startPolicy}" == 'ADMIN_ONLY' ]]; then + printInfo "No changes needed, exiting. The cluster '${clusterName}' is already stopped or stopping. The effective value of spec.clusters[?(clusterName="${clusterName}"].serverStartPolicy attribute on the domain resource is 'NEVER' or 'ADMIN_ONLY'." + exit 0 +fi + +# Set policy value to NEVER +printInfo "Patching start policy of cluster '${clusterName}' from '${startPolicy}' to 'NEVER'." +createPatchJsonToUpdateClusterPolicy "${domainJson}" "${clusterName}" "NEVER" patchJson + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Successfully patched cluster '${clusterName}' with 'NEVER' start policy!" diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopDomain.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopDomain.sh new file mode 100644 index 000000000..d62f6b280 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopDomain.sh @@ -0,0 +1,95 @@ +# !/bin/sh +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh + +function usage() { + + cat << EOF + + This script stops a deployed WebLogic domain by patching + 'spec.serverStartPolicy' attribute of domain resource to 'NEVER'. + This change will cause the operator to initiate shutdown of the + domain's WebLogic server instance pods if the pods are running. + + Usage: + + $(basename $0) [-n mynamespace] [-d mydomainuid] [-m kubecli] + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -m : Kubernetes command line interface. Default is 'kubectl' if KUBERNETES_CLI env + variable is not set. Otherwise default is the value of KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +verboseMode=false + +while getopts "vn:d:m:h" opt; do + case $opt in + n) domainNamespace="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +set -eu +set -o pipefail + +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) + +if [ -z "${domainJson}" ]; then + printError "Domain resource for domain '${domainUid}' not found in namespace '${domainNamespace}'. Exiting." + exit 1 +fi + +getDomainPolicy "${domainJson}" serverStartPolicy + +if [ "${serverStartPolicy}" == 'NEVER' ]; then + printInfo "No changes needed, exiting. The domain '${domainUid}' is already stopped or stopping. The value of 'spec.serverStartPolicy' attribute on the domain resource is 'NEVER'." + exit 0 +fi + +printInfo "Patching domain '${domainUid}' in namespace '${domainNamespace}' from serverStartPolicy='${serverStartPolicy}' to 'NEVER'." + +createPatchJsonToUpdateDomainPolicy "NEVER" patchJson + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Successfully patched domain '${domainUid}' in namespace '${domainNamespace}' with 'NEVER' start policy!" diff --git a/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopServer.sh b/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopServer.sh new file mode 100644 index 000000000..ec35b4d97 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/domain-lifecycle/stopServer.sh @@ -0,0 +1,248 @@ +# !/bin/sh +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +# This script stops a WebLogic managed server in a domain. +# Internal code notes :- +# - If server start policy is NEVER or policy is IF_NEEDED and the server is not +# selected to start based on the replica count, it means that server is already +# stopped or is in the process of stopping. In this case, script exits without +# making any changes. +# +# - If server is part of a cluster and keep_replica_constant option is false (the default) +# and the effective start policy of the server is IF_NEEDED and decreasing replica count +# will naturally stop the server, the script decreases the replica count. +# +# - If server is part of a cluster and keep_replica_constant option is false (the default) +# and unsetting policy and decreasing the replica count will stop the server, script +# unsets the policy and decreases replica count. For e.g. if replica count is 2 and +# start policy of server2 is ALWAYS, unsetting policy and decreasing replica count will +# stop server2. +# +# - If option to keep replica count constant ('-k') is selected and unsetting start policy +# will naturally stop the server, script will unset the policy. For e.g. if replica count +# is 1 and start policy of server2 is ALWAYS, unsetting policy will stop server2. +# +# - If above conditions are not true, it implies that server policy is IF_NEEDED and server +# is selected to start. In this case, script sets start policy to NEVER. For e.g. replica +# count is 2 and server1 needs to be stopped. The script also decrements the replica count +# by default. If option to keep replica count constant ('-k') is selected, it only sets the +# start policy to NEVER. +# + +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/helper.sh +if [ "${debug}" == "true" ]; then set -x; fi; +set -eu + +function usage() { + + cat << EOF + + This script stops a running WebLogic server in a domain. For managed servers, it either + decreases the value of 'spec.clusters[].replicas' or updates the + 'spec.managedServers[].serverStartPolicy' attribute of the domain + resource or both as necessary to stop the server. For the administration server, it updates + the value of 'spec.adminServer.serverStartPolicy' attribute of the domain resource. The + 'spec.clusters[].replicas' value can be kept constant by using '-k' option. + Please see README.md for more details. + + Usage: + + $(basename $0) -s myserver [-n mynamespace] [-d mydomainuid] [-k] [-m kubecli] [-v] + + -s : The WebLogic server name (not the pod name). + This parameter is required. + + -d : Domain unique-id. Default is 'sample-domain1'. + + -n : Domain namespace. Default is 'sample-domain1-ns'. + + -k : Keep replica count constant for the clustered servers. The default behavior + is to decrement the replica count for the clustered servers. This parameter + is ignored for the administration and non-clustered managed servers. + + -m : Kubernetes command line interface. Default is 'kubectl' if KUBERNETES_CLI env + variable is not set. Otherwise default is the value of KUBERNETES_CLI env variable. + + -v : Enables verbose mode. Default is 'false'. + + -h : This help. + +EOF +exit $1 +} + +kubernetesCli=${KUBERNETES_CLI:-kubectl} +serverName="" +clusterName="" +domainUid="sample-domain1" +domainNamespace="sample-domain1-ns" +keepReplicaConstant=false +verboseMode=false +serverStartPolicy=NEVER +serverStarted="" +effectivePolicy="" +managedServerPolicy="" +stoppedWhenAlwaysPolicyReset="" +replicasEqualsMinReplicas="" +withReplicas="CONSTANT" +withPolicy="CONSTANT" +patchJson="" +isAdminServer=false + +while getopts "vks:m:n:d:h" opt; do + case $opt in + s) serverName="${OPTARG}" + ;; + n) domainNamespace="${OPTARG}" + ;; + m) kubernetesCli="${OPTARG}" + ;; + d) domainUid="${OPTARG}" + ;; + k) keepReplicaConstant=true; + ;; + v) verboseMode=true; + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +# +# Function to perform validations, read files and initialize workspace +# +function initialize { + + validateErrors=false + + validateKubernetesCliAvailable + validateJqAvailable + + # Validate that server name parameter is specified. + if [ -z "${serverName}" ]; then + validationError "Please specify the server name using '-s' parameter e.g. '-s managed-server1'." + fi + + failIfValidationErrors +} + +initialize + +# Get the domain in json format +domainJson=$(${kubernetesCli} get domain ${domainUid} -n ${domainNamespace} -o json --ignore-not-found) +if [ -z "${domainJson}" ]; then + printError "Unable to get domain resource for domain '${domainUid}' in namespace '${domainNamespace}'. Please make sure the 'domain_uid' and 'namespace' specified by the '-d' and '-n' arguments are correct. Exiting." + exit 1 +fi + +# Validate that specified server is either part of a cluster or is an independent managed server +validateServerAndFindCluster "${domainUid}" "${domainNamespace}" "${serverName}" isValidServer clusterName isAdminServer +if [ "${isValidServer}" != 'true' ]; then + printError "Server ${serverName} is not part of any cluster and it's not an independent managed server. Please make sure that server name specified is correct." + exit 1 +fi + +getEffectivePolicy "${domainJson}" "${serverName}" "${clusterName}" effectivePolicy +if [ "${isAdminServer}" == 'true' ]; then + getEffectiveAdminPolicy "${domainJson}" effectivePolicy + if [ "${effectivePolicy}" == "NEVER" ]; then + printInfo "No changes needed, exiting. Server should be already stopping or stopped because effective sever start policy is 'NEVER'." + exit 0 + fi +fi + +if [ -n "${clusterName}" ]; then + # Server is part of a cluster, check currently started servers + checkStartedServers "${domainJson}" "${serverName}" "${clusterName}" "${withReplicas}" "${withPolicy}" serverStarted + if [[ "${effectivePolicy}" == "NEVER" || "${effectivePolicy}" == "ADMIN_ONLY" || "${serverStarted}" != "true" ]]; then + printInfo "No changes needed, exiting. Server should be already stopping or stopped. This is either because of the sever start policy or server is chosen to be stopped based on current replica count." + exit 0 + fi +else + # Server is an independent managed server. + if [ "${effectivePolicy}" == "NEVER" ] || [[ "${effectivePolicy}" == "ADMIN_ONLY" && "${isAdminServer}" != 'true' ]]; then + printInfo "No changes needed, exiting. Server should be already stopping or stopped because effective sever start policy is 'NEVER' or 'ADMIN_ONLY'." + exit 0 + fi +fi + +if [[ -n "${clusterName}" && "${keepReplicaConstant}" == 'false' ]]; then + # check if replica count can decrease below current value + isReplicaCountEqualToMinReplicas "${domainJson}" "${clusterName}" replicasEqualsMinReplicas + if [ "${replicasEqualsMinReplicas}" == 'true' ]; then + printInfo "Not decreasing the replica count value: it is at its minimum. \ + (See 'domain.spec.allowReplicasBelowMinDynClusterSize' and \ + 'domain.status.clusters[].minimumReplicas' for details)." + keepReplicaConstant=true + fi +fi + +# Create server start policy patch with NEVER value +createServerStartPolicyPatch "${domainJson}" "${serverName}" "${serverStartPolicy}" neverStartPolicyPatch +getServerPolicy "${domainJson}" "${serverName}" managedServerPolicy +if [ -n "${managedServerPolicy}" ]; then + effectivePolicy=${managedServerPolicy} +fi +if [[ -n "${clusterName}" && "${effectivePolicy}" == "ALWAYS" ]]; then + # Server is part of a cluster and start policy is ALWAYS. + withReplicas="CONSTANT" + withPolicy="UNSET" + checkStartedServers "${domainJson}" "${serverName}" "${clusterName}" "${withReplicas}" "${withPolicy}" startedWhenAlwaysPolicyReset +fi + +if [[ -n "${clusterName}" && "${keepReplicaConstant}" != 'true' ]]; then + # server is part of a cluster and replica count will decrease + withReplicas="DECREASED" + withPolicy="UNSET" + checkStartedServers "${domainJson}" "${serverName}" "${clusterName}" "${withReplicas}" "${withPolicy}" startedWhenRelicaReducedAndPolicyReset + createReplicaPatch "${domainJson}" "${clusterName}" "DECREMENT" replicaPatch replicaCount + + if [[ -n ${managedServerPolicy} && "${startedWhenRelicaReducedAndPolicyReset}" != "true" ]]; then + # Server shuts down by unsetting start policy and decrementing replica count, unset and decrement + printInfo "Unsetting the current start policy '${managedServerPolicy}' for '${serverName}' \ + and decrementing replica count to ${replicaCount}." + createPatchJsonToUnsetPolicyAndUpdateReplica "${domainJson}" "${serverName}" "${replicaPatch}" patchJson + elif [[ -z ${managedServerPolicy} && "${startedWhenRelicaReducedAndPolicyReset}" != "true" ]]; then + # Start policy is not set, server shuts down by decrementing replica count, decrement replicas + printInfo "Updating replica count for cluster ${clusterName} to ${replicaCount}." + createPatchJsonToUpdateReplica "${replicaPatch}" patchJson + elif [[ ${managedServerPolicy} == "ALWAYS" && "${startedWhenAlwaysPolicyReset}" != "true" ]]; then + # Server shuts down by unsetting the start policy, unset and decrement replicas + printInfo "Unsetting the current start policy '${managedServerPolicy}' for '${serverName}' \ + and decrementing replica count to ${replicaCount}." + createPatchJsonToUnsetPolicyAndUpdateReplica "${domainJson}" "${serverName}" "${replicaPatch}" patchJson + else + # Patch server start policy to NEVER and decrement replica count + printInfo "Patching start policy of server '${serverName}' from '${effectivePolicy}' to 'NEVER' \ + and decrementing replica count for cluster '${clusterName}' to ${replicaCount}." + createPatchJsonToUpdateReplicaAndPolicy "${replicaPatch}" "${neverStartPolicyPatch}" patchJson + fi +elif [[ -n ${clusterName} && "${keepReplicaConstant}" == 'true' ]]; then + # Server is part of a cluster and replica count needs to stay constant + if [[ ${managedServerPolicy} == "ALWAYS" && "${startedWhenAlwaysPolicyReset}" != "true" ]]; then + # Server start policy is AlWAYS and server shuts down by unsetting the policy, unset policy + printInfo "Unsetting the current start policy '${effectivePolicy}' for '${serverName}'." + createPatchJsonToUnsetPolicy "${domainJson}" "${serverName}" patchJson + else + # Patch server start policy to NEVER + printInfo "Patching start policy of '${serverName}' from '${effectivePolicy}' to 'NEVER'." + createPatchJsonToUpdatePolicy "${neverStartPolicyPatch}" patchJson + fi +elif [ "${isAdminServer}" == 'true' ]; then + printInfo "Patching start policy of '${serverName}' from '${effectivePolicy}' to 'NEVER'." + createPatchJsonToUpdateAdminPolicy "${domainJson}" "${serverStartPolicy}" patchJson +else + # Server is an independent managed server, patch server start policy to NEVER + printInfo "Patching start policy of '${serverName}' from '${effectivePolicy}' to 'NEVER'." + createPatchJsonToUpdatePolicy "${neverStartPolicyPatch}" patchJson +fi + +executePatchCommand "${kubernetesCli}" "${domainUid}" "${domainNamespace}" "${patchJson}" "${verboseMode}" + +printInfo "Patch command succeeded !" diff --git a/OracleWebCenterPortal/kubernetes/elasticsearch-and-kibana/README.md b/OracleWebCenterPortal/kubernetes/elasticsearch-and-kibana/README.md new file mode 100644 index 000000000..bd62bcc56 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/elasticsearch-and-kibana/README.md @@ -0,0 +1,31 @@ +# Sample to deploy Elasticsearch and Kibana + + +When you install the WebLogic operator Helm chart, you can set +`elkIntegrationEnabled` to `true` in your `values.yaml` file to tell the operator to send the contents of the operator's logs to Elasticsearch. + +Typically, you would have already configured Elasticsearch and Kibana in the +Kubernetes cluster, and also would have specified `elasticSearchHost` and `elasticSearchPort` in your `values.yaml` file to point to where Elasticsearch is already running. + +This sample configures the Elasticsearch and Kibana deployments and services. +It's useful for trying out the operator in a Kubernetes cluster that doesn't already +have them configured. + +It runs the Elastic Stack on the same host and port that the operator's Helm chart defaults +to, therefore, you only need to set `elkIntegrationEnabled` to `true` in your +`values.yaml` file. + +To control Elasticsearch memory parameters (Heap allocation and Enabling/Disabling swapping) please open the file `elasticsearch_and_kibana.yaml`, search for env variables of the elasticsearch container and change the values of the following. + +* ES_JAVA_OPTS: value may contain for example -Xms512m -Xmx512m to lower the default memory usage (please be aware that this value is only applicable for demo purpose and it is not the one recommended by Elasticsearch itself) +* bootstrap.memory_lock: value may contain true (enables the usage of mlockall to try to lock the process address space into RAM, preventing any Elasticsearch memory from being swapped out) or false (disables the usage of mlockall to try to lock the process address space into RAM, preventing any Elasticsearch memory from being swapped out). + +To install Elasticsearch and Kibana, use: +```shell +$ kubectl apply -f kubernetes/samples/scripts/elasticsearch-and-kibana/elasticsearch_and_kibana.yaml +``` + +To remove them, use: +```shell +$ kubectl delete -f kubernetes/samples/scripts/elasticsearch-and-kibana/elasticsearch_and_kibana.yaml +``` diff --git a/OracleWebCenterPortal/kubernetes/elasticsearch-and-kibana/elasticsearch_and_kibana.yaml b/OracleWebCenterPortal/kubernetes/elasticsearch-and-kibana/elasticsearch_and_kibana.yaml new file mode 100644 index 000000000..97b0b9186 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/elasticsearch-and-kibana/elasticsearch_and_kibana.yaml @@ -0,0 +1,117 @@ +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# When a user installs the WebLogic operator Helm chart, the user can set +# elkIntegrationEnabled to true in their values.yaml to tell the operator to send the +# contents of the operator's log to Elasticsearch. +# +# Typically, a user would have already configured Elasticsearch and Kibana in the +# Kubernetes cluster, and also would specify elasticSearchHost and elasticSearchPort +# in their values.yaml file to point to where Elasticsearch is already running. +# +# This sample configures the Elasticsearch and Kibana deployments and services. +# It's useful for trying out the operator in a Kubernetes cluster that doesn't already +# have them configured. +# +# It runs Elasticstack on the same host and port that the operator's Helm chart defaults +# to, therefore, the customer only needs to set elkIntegrationEnabled to true in their +# values.yaml file. +# +# To configure them, use: +# kubectl apply -f kubernetes/samples/scripts/elasticsearch_and_kibana.yaml +# +# To remove them, use: +# kubectl delete -f kubernetes/samples/scripts/elasticsearch_and_kibana.yaml + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: "default" + name: "elasticsearch" + labels: + app: "elasticsearch" +spec: + replicas: 1 + selector: + matchLabels: + app: "elasticsearch" + template: + metadata: + labels: + app: "elasticsearch" + spec: + initContainers: + - name: set-vm-max-map-count + image: busybox + imagePullPolicy: IfNotPresent + command: ['sysctl', '-w', 'vm.max_map_count=262144'] + securityContext: + privileged: true + containers: + - name: "elasticsearch" + image: "elasticsearch:6.8.0" + ports: + - containerPort: 9200 + - containerPort: 9300 + env: + - name: ES_JAVA_OPTS + value: -Xms1024m -Xmx1024m + +--- +kind: "Service" +apiVersion: "v1" +metadata: + namespace: "default" + name: "elasticsearch" +spec: + ports: + - name: "http" + protocol: "TCP" + port: 9200 + targetPort: 9200 + - name: "https" + protocol: "TCP" + port: 9300 + targetPort: 9300 + selector: + app: "elasticsearch" + +--- +apiVersion: "apps/v1" +kind: "Deployment" +metadata: + namespace: "default" + name: "kibana" + labels: + app: "kibana" +spec: + replicas: 1 + selector: + matchLabels: + app: "kibana" + template: + metadata: + labels: + app: "kibana" + spec: + containers: + - name: "kibana" + image: "kibana:6.8.0" + ports: + - containerPort: 5601 + +--- +apiVersion: "v1" +kind: "Service" +metadata: + namespace: "default" + name: "kibana" + labels: + app: "kibana" +spec: + type: "NodePort" + ports: + - port: 5601 + selector: + app: "kibana" diff --git a/OracleWebCenterPortal/kubernetes/imagetool-scripts/buildArgs b/OracleWebCenterPortal/kubernetes/imagetool-scripts/buildArgs index 58be2ac87..1a3abf42f 100755 --- a/OracleWebCenterPortal/kubernetes/imagetool-scripts/buildArgs +++ b/OracleWebCenterPortal/kubernetes/imagetool-scripts/buildArgs @@ -4,6 +4,7 @@ create --version=12.2.1.4.0 --tag=oracle/wcportal:12.2.1.4 --pull +--fromImage ghcr.io/oracle/oraclelinux:7-slim --additionalBuildCommands /docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0/additionalBuildCmds.txt --additionalBuildFiles /docker-images/OracleWebCenterPortal/dockerfiles/12.2.1.4/container-scripts --opatchBugNumber 28186730_13.9.4.2.5 diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/README.md b/OracleWebCenterPortal/kubernetes/ingress-per-domain/README.md deleted file mode 100755 index 7b7e89972..000000000 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# An Ingress per domain chart -This chart is for deploying an Ingress resource in front of a WebLogic domain cluster. We support three Ingress types: Traefik, Voyager, Nginx. - -## Prerequisites -- Have Docker and a Kubernetes cluster running and have `kubectl` installed and configured. -- Have Helm installed. -- The corresponding Ingress controller, Traefik or Voyager, is installed in the Kubernetes cluster. -- A WebLogic domain cluster deployed by `weblogic-operator` is running in the Kubernetes cluster. - -## Generate Secret to access SSL services - -Command to Generate Secret: -``` -$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" -$ kubectl -n wcpns create secret tls domain1-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt - -``` - -## Installing the chart - -To install the chart with the release name, `my-ingress`, with the given `values.yaml`: -``` -# Change directory to the cloned git weblogic-kubernetes-operator repo. -$ cd kubernetes/samples/charts - -# Use helm to install the chart. Use `--namespace` to specify the name of the WebLogic domain's namespace. -$ helm install ingress-per-domain --name my-ingress --namespace my-domain-namespace --values values.yaml -``` -The Ingress resource will be created in the same namespace as the WebLogic domain cluster. - -Sample `values.yaml` for the Traefik Ingress: -``` -type: TRAEFIK - -# WLS domain as backend to the load balancer -wlsDomain: - domainUID: domain1 - clusterName: cluster1 - managedServerPort: 8001 - -# Traefik specific values -traefik: - # hostname used by host-routing - hostname: domain1.org -``` - -Sample `values.yaml` for the Voyager Ingress: -``` -type: VOYAGER - -# WLS domain as backend to the load balancer -wlsDomain: - domainUID: domain1 - clusterName: cluster1 - managedServerPort: 8001 - -# Voyager specific values -voyager: - # web port - webPort: 30305 - # stats port - statsPort: 30315 -``` -Sample `values.yaml` for the NGINX Ingress: -``` -type: NGINX - -# WLS domain as backend to the load balancer -wlsDomain: - domainUID: domain1 - clusterName: cluster1 - managedServerPort: 8001 - -# nginx specific values -nginx: - connectTimeout: 1800 - readTimeout: 1800 - sendTimeout: 1800 - cookieExpires: 172800 - cookieMaxAge: 172800 -``` -## Uninstalling the chart -To uninstall and delete the `my-ingress` deployment: -``` -$ helm delete --purge my-ingress -``` -## Configuration -The following table lists the configurable parameters of this chart and their default values. - -| Parameter | Description | Default | -| --- | --- | --- | -| `type` | Type of Ingress controller. Legal values are `TRAEFIK` or `VOYAGER`. | `TRAEFIK` | -| `wlsDomain.domainUID` | DomainUID of the WLS domain. | `domain1` | -| `wlsDomain.clusterName` | Cluster name in the WLS domain. | `cluster-1` | -| `wlsDomain.managedServerPort` | Port number of the managed servers in the WLS domain cluster. | `8001` | -| `traefik.hostname` | Hostname to route to the WLS domain cluster. | `domain1.org` | -| `voyager.webPort` | Web port to access the Voyager load balancer. | `30305` | -| `voyager.statsPort` | Port to access the Voyager/HAProxy stats page. | `30315` | - -**Note:** The input values `domainUID` and `clusterName` will be used to generate the Kubernetes `serviceName` of the WLS cluster with the format `domainUID-cluster-clusterName`. diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/nginx-ingress.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/nginx-ingress.yaml deleted file mode 100755 index 51479d7fe..000000000 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/nginx-ingress.yaml +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - -{{- if eq .Values.type "NGINX" }} ---- -apiVersion: {{ .Values.apiVersion }} -kind: Ingress -metadata: - name: {{ .Values.wlsDomain.domainUID }}-ingress - namespace: {{ .Release.Namespace }} - annotations: -{{- if eq .Values.tls "SSL" }} - kubernetes.io/ingress.class: nginx - nginx.ingress.kubernetes.io/configuration-snippet: | - more_set_input_headers "X-Forwarded-Proto: https"; - more_set_input_headers "WL-Proxy-SSL: true"; - nginx.ingress.kubernetes.io/ingress.allow-http: "false" -{{- end }} - nginx.ingress.kubernetes.io/proxy-connect-timeout: "{{ .Values.ngnix.connectTimeout }}" - nginx.ingress.kubernetes.io/proxy-read-timeout: "{{ .Values.ngnix.readTimeout }}" - nginx.ingress.kubernetes.io/proxy-send-timeout: "{{ .Values.ngnix.sendTimeout }}" - nginx.ingress.kubernetes.io/affinity: "cookie" - nginx.ingress.kubernetes.io/session-cookie-name: "stickyid" - nginx.ingress.kubernetes.io/session-cookie-expires: "{{ .Values.ngnix.cookieExpires }}" - nginx.ingress.kubernetes.io/session-cookie-max-age: "{{ .Values.ngnix.cookieMaxAge }}" - nginx.ingress.kubernetes.io/ssl-redirect: "false" - nginx.ingress.kubernetes.io/affinity-mode: persistent -spec: - rules: - - host: '{{ .Values.nginx.hostname }}' - http: - paths: - - path: /webcenter - backend: - serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /console - backend: - serviceName: '{{ .Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName| lower }}' - servicePort: {{.Values.wlsDomain.adminServerPort}} - - path: /rsscrawl - backend: - serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /webcenterhelp - backend: - serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /rest - backend: - serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /em - backend: - serviceName: '{{ .Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName| lower }}' - servicePort: {{.Values.wlsDomain.adminServerPort}} - {{- if eq .Values.tls "SSL" }} -tls: - - hosts: - - '{{ .Values.nginx.hostname }}' - secretName: domain1-tls-cert -{{- end }} - {{- end }} diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/traefik-ingress.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/traefik-ingress.yaml deleted file mode 100755 index 7994e11ff..000000000 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/traefik-ingress.yaml +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - -{{- if eq .Values.type "TRAEFIK" }} ---- -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ .Values.wlsDomain.domainUID }}-traefik - namespace: {{ .Release.Namespace }} - annotations: - kubernetes.io/ingress.class: traefik -{{- if eq .Values.tls "SSL" }} - traefik.ingress.kubernetes.io/router.entrypoints: websecure - traefik.ingress.kubernetes.io/router.tls: "true" - traefik.ingress.kubernetes.io/router.middlewares: wcpns-wls-proxy-ssl@kubernetescrd -{{- end }} -spec: - rules: - - host: '{{ .Values.traefik.hostname }}' - http: - paths: - - path: /webcenter - backend: - serviceName: '{{ .Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /console - backend: - serviceName: '{{.Values.wlsDomain.domainUID}}-{{.Values.wlsDomain.adminServerName| lower}}' - servicePort: {{.Values.wlsDomain.adminServerPort}} - - path: /rsscrawl - backend: - serviceName: '{{.Values.wlsDomain.domainUID}}-cluster-{{.Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /webcenterhelp - backend: - serviceName: '{{.Values.wlsDomain.domainUID}}-cluster-{{.Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /rest - backend: - serviceName: '{{.Values.wlsDomain.domainUID}}-cluster-{{.Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /em - backend: - serviceName: '{{.Values.wlsDomain.domainUID}}-{{.Values.wlsDomain.adminServerName| lower}}' - servicePort: {{.Values.wlsDomain.adminServerPort}} - - {{- if eq .Values.tls "SSL" }} - tls: - - hosts: - - '{{ .Values.traefik.hostname }}' - secretName: wcpinfra-tls-cert -{{- end }} -{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/voyager-ingress.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/voyager-ingress.yaml deleted file mode 100755 index 69ce7147e..000000000 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/templates/voyager-ingress.yaml +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - -{{- if eq .Values.type "VOYAGER" }} ---- -apiVersion: voyager.appscode.com/v1beta1 -kind: Ingress -metadata: - name: {{ .Values.wlsDomain.domainUID }}-voyager - namespace: {{ .Release.Namespace }} - annotations: - ingress.appscode.com/type: 'NodePort' - ingress.appscode.com/stats: 'true' - ingress.appscode.com/affinity: 'cookie' -spec: -{{- if eq .Values.tls "SSL" }} - frontendRules: - - port: 443 - rules: - - http-request set-header WL-Proxy-SSL true - tls: - - secretName: wcpinfra-tls-cert - hosts: - - '*' -{{- end }} - rules: - - host: '*' - http: - nodePort: '{{ .Values.voyager.webPort }}' - paths: - - path: /webcenter - backend: - serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /console - backend: - serviceName: '{{.Values.wlsDomain.domainUID }}-{{ .Values.wlsDomain.adminServerName| lower}}' - servicePort: {{.Values.wlsDomain.adminServerPort}} - - path: /rsscrawl - backend: - serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /rest - backend: - serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /webcenterhelp - backend: - serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' - servicePort: {{.Values.wlsDomain.managedServerPort}} - - path: /em - backend: - serviceName: '{{.Values.wlsDomain.domainUID}}-{{.Values.wlsDomain.adminServerName| lower}}' - servicePort: {{.Values.wlsDomain.adminServerPort}} -# - path: /wls-exporter -# backend: -# serviceName: '{{.Values.wlsDomain.domainUID }}-cluster-{{ .Values.wlsDomain.clusterName | lower}}' -# servicePort: {{.Values.wlsDomain.managedServerPort}} - ---- -apiVersion: v1 -kind: Service -metadata: - name: {{.Values.wlsDomain.domainUID}}-voyager-stats - namespace: {{.Release.Namespace}} - labels: - weblogic.resourceVersion: domain-v2 -spec: - type: NodePort - ports: - - name: client - protocol: TCP - port: 56789 - targetPort: 56789 - nodePort: {{.Values.voyager.statsPort}} - selector: - origin: voyager - origin-name: {{.Values.wlsDomain.domainUID}}-voyager -{{- end }} diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/voyager-tls.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/voyager-tls.yaml deleted file mode 100755 index dc41c6648..000000000 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/tls/voyager-tls.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - -apiVersion: voyager.appscode.com/v1beta1 -kind: Ingress -metadata: - name: voyager-endtoendssl - namespace: wcpns - annotations: - ingress.appscode.com/type: 'NodePort' - ingress.appscode.com/stats: 'true' - ingress.appscode.com/affinity: 'cookie' - ingress.appscode.com/ssl-passthrough: "true" -spec: - tls: - - secretName: domain1-tls-cert - hosts: - - '*' - rules: - - host: '*' - http: - nodePort: '31443' - paths: - - path: / - backend: - serviceName: wcp-domain-cluster-wcp-cluster - servicePort: '8889' diff --git a/OracleWebCenterPortal/kubernetes/ingress-per-domain/values.yaml b/OracleWebCenterPortal/kubernetes/ingress-per-domain/values.yaml deleted file mode 100755 index 6a032d868..000000000 --- a/OracleWebCenterPortal/kubernetes/ingress-per-domain/values.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2021, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - -# Default values for ingress-per-domain. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -apiVersion: networking.k8s.io/v1beta1 - -# Load balancer type. Supported values are: TRAEFIK, VOYAGER ,NGINX -type: TRAEFIK -# Supported values NONSSL ,SSL -tls: NONSSL - -# WLS domain as backend to the load balancer -wlsDomain: - domainUID: wcp-domain - clusterName: wcp-cluster - managedServerPort: 8888 - adminServerPort: 7001 - adminServerName: adminserver - -# Traefik specific values -traefik: - # hostname used by host-routing - hostname: domain1.org - -# Voyager specific values -voyager: - # web port - webPort: 30305 - # stats port - statsPort: 30315 - -# Ngnix specific values -nginx: - connectTimeout: 1800 - readTimeout: 1800 - sendTimeout: 1800 - cookieExpires: 172800 - cookieMaxAge: 172800 diff --git a/OracleWebCenterPortal/kubernetes/logging-services/logstash/README.md b/OracleWebCenterPortal/kubernetes/logging-services/logstash/README.md new file mode 100644 index 000000000..fb55c56df --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/logging-services/logstash/README.md @@ -0,0 +1,59 @@ +## Publish OracleWebCenterPortal server and diagnostics logs into Elasticsearch + +## Prerequisites +See [here](https://oracle.github.io/weblogic-kubernetes-operator/samples/simple/elastic-stack/) for the steps to integrate Elasticsearch for the WebLogic Kubernetes operator. + +Before deploying the WebLogic Kubernetes operator edit `values.yaml` in weblogic-kubernetes-operator/kubernetes/charts/weblogic-operator/ to enable elastic search integration. +Configure the following variables: +```bash +# elkIntegrationEnabled specifies whether or not ELK integration is enabled. +elkIntegrationEnabled: true +# logStashImage specifies the docker image containing logstash. +# This parameter is ignored if 'elkIntegrationEnabled' is false. +logStashImage: "logstash:6.6.0" + +# elasticSearchHost specifies the hostname of where Elasticsearch is running. +# This parameter is ignored if 'elkIntegrationEnabled' is false. +elasticSearchHost: "elasticsearch.default.svc.cluster.local" + +# elasticSearchPort specifies the port number of where Elasticsearch is running. +# This parameter is ignored if 'elkIntegrationEnabled' is false. +elasticSearchPort: 9200 +``` +Deployment of WebLogic Kubernetes operator with above changes, will create an additional logstash container as sidecar. This logstash container will push the operator logs to the configured Elasticsearch server. + +### WebLogic Server logs + +The WebLogic server logs or diagnostics logs can be pushed to Elasticsearch server using logstash pod. The logstash pod should have access to the shared domain home or the log location. The persistent volume of the domain home can be used in the logstash pod. + +### Create the logstash pod + +1. Get Domain home persistence volume claim details +Get the persistent volume details of the domain home of the WebLogic server(s). + + ```bash + $ kubectl get pvc -n wcpns + ``` + +1. Create logstash configuration. +Create logstash configuration file. The logstash configuration file can be loaded from a volume. + ```bash + $ kubectl cp logstash.conf wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains --namespace wcpns + ``` + + You can use sample logstash configuration file generated to push server and diagnostic logs of all servers available at DOMAIN_HOME/servers//logs/-diagnostic.log + +1. Copy the logstash.conf into say /u01/oracle/user_projects/domains so that it can be used for logstash deployment, using Administration Server pod + +1. Create deployment YAML for logstash pod. +You can use sample logstash.yaml file generated to create deployment for logstash pod. The mounted persistent volume of the domain home will provide access to the WebLogic server logs to logstash pod. +Make sure to point the logstash configuration file to correct location and also correct domain home persistence volume claim. + +1. Deploy logstash to start publish logs to Elasticsearch: + + ```bash + $ kubectl create -f logstash.yaml + ``` + +1. Now, you can view the diagnostics logs using Kibana with index pattern `logstash-*`. + diff --git a/OracleWebCenterPortal/kubernetes/logging-services/logstash/logstash.conf b/OracleWebCenterPortal/kubernetes/logging-services/logstash/logstash.conf new file mode 100644 index 000000000..ea9487e11 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/logging-services/logstash/logstash.conf @@ -0,0 +1,25 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +input { + file { + path => "/u01/oracle/user_projects/domains/wcp-domain/servers/**/logs/*-diagnostic.log" + start_position => beginning + } + file { + path => "/u01/oracle/user_projects/domains/logs/wcp-domain/*.log" + start_position => beginning + } +} + +filter { + grok { + match => [ "message", "<%{DATA:log_timestamp}> <%{WORD:log_level}> <%{WORD:thread}> <%{HOSTNAME:hostname}> <%{HOSTNAME:servername}> <%{DATA:timer}> <<%{DATA:kernel}>> <> <%{DATA:uuid}> <%{NUMBER:timestamp}> <%{DATA:misc}> <%{DATA:log_number}> <%{DATA:log_message}>" ] + } +} +output { + elasticsearch { + hosts => ["elasticsearch.default.svc.cluster.local:9200"] + } +} diff --git a/OracleWebCenterPortal/kubernetes/logging-services/logstash/logstash.yaml b/OracleWebCenterPortal/kubernetes/logging-services/logstash/logstash.yaml new file mode 100644 index 000000000..c1938a090 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/logging-services/logstash/logstash.yaml @@ -0,0 +1,39 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: logstash + namespace: wcpns +spec: + selector: + matchLabels: + app: logstash + template: # create pods using pod definition in this template + metadata: + labels: + app: logstash + spec: + volumes: + - name: domain-storage-volume + persistentVolumeClaim: + claimName: wcp-domain-domain-pvc + - name: shared-logs + emptyDir: {} + containers: + - name: logstash + image: logstash:6.6.0 + command: ["/bin/sh"] + args: ["/usr/share/logstash/bin/logstash", "-f", "/u01/oracle/user_projects/domains/logstash.conf"] + imagePullPolicy: IfNotPresent + volumeMounts: + - mountPath: /u01/oracle/user_projects/domains + name: domain-storage-volume + - name: shared-logs + mountPath: /shared-logs + ports: + - containerPort: 5044 + name: logstash + diff --git a/OracleWebCenterPortal/kubernetes/logging-services/weblogic-logging-exporter/README.md b/OracleWebCenterPortal/kubernetes/logging-services/weblogic-logging-exporter/README.md new file mode 100644 index 000000000..2de15b340 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/logging-services/weblogic-logging-exporter/README.md @@ -0,0 +1,131 @@ +## Publish WebLogic Server logs into Elasticsearch + +The WebLogic Logging Exporter adds a log event handler to WebLogic Server, such that WebLogic Server logs can be integrated into Elastic Stack in Kubernetes directly, by using the Elasticsearch REST API. + +## Prerequisite + +This document assumes that you have already deployed Elasticsearch/Kibana environment. If you have not, please use a sample/demo deployment of Elasticsearch/Kibana from WebLogic Kubernetes operator. + +To deploy Elasticsearch and Kibana on the Kubernetes cluster: +```bash +$ kubectl create -f https://raw.githubusercontent.com/oracle/weblogic-kubernetes-operator/master/kubernetes/samples/scripts/elasticsearch-and-kibana/elasticsearch_and_kibana.yaml +``` + +Follow these steps to setup WebLogic Logging Exporter in a WebLogic operator environment and push the WebLogic server logs to Elasticsearch/Kibana + +1. Download WebLogic logging exporter binaries + + The WebLogic logging exporter pre-built binaries are available in the github releases page: [Release 1.0.1](https://github.com/oracle/weblogic-logging-exporter/releases) + + ```bash + $ wget https://github.com/oracle/weblogic-logging-exporter/releases/download/v1.0.1/weblogic-logging-exporter.jar + ``` + + Download weblogic-logging-exporter.jar from the github release link above. Also download dependency jar - snakeyaml-1.27.jar from Maven Central. + + ```bash + $ wget -O snakeyaml-1.27.jar https://search.maven.org/remotecontent?filepath=org/yaml/snakeyaml/1.27/snakeyaml-1.27.jar + ``` +1. Copy JAR files into the Kubernetes WebLogic Administration Server Pod + + Copy weblogic-logging-exporter.jar and snakeyaml-1.27.jar to the domain home folder in the Administration server pod. + + ```bash + $ kubectl cp weblogic-logging-exporter.jar wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/ + $ kubectl cp snakeyaml-1.27.jar wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/ + ``` + +1. Add a startup class to the domain configuration + + In this step, we configure weblogic-logging-exporter JAR as a startup class in the WebLogic servers where we intend to collect the logs. + + a) In the Administration Console, navigate to `Environment` then `Startup and Shutdown classes` in the main menu. + + b) Add a new Startup class. You may choose any descriptive name and the class name must be `weblogic.logging.exporter.Startup`. + + c) Target the startup class to each server that you want to export logs from. + + You can verify this by checking for the update in your config.xml which should be similar to this example: + + ```bash + + LoggingExporterStartupClass + AdminServer + weblogic.logging.exporter.Startup + + ``` + +1. Update WebLogic Server CLASS Path. + + In this step, we set the class path for weblogic-logging-exporter and its dependencies. + + a) Copy setDomainEnv.sh from the pod to local folder. + ```bash + $ kubectl cp wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/bin/setDomainEnv.sh setDomainEnv.sh + ``` + b) Modify setDomainEnv.sh to update the Server Class path. + ```bash + CLASSPATH=/u01/oracle/user_projects/domains/wcp-domain/weblogic-logging-exporter.jar:/u01/oracle/user_projects/domains/wcp-domain/snakeyaml-1.27.jar:${CLASSPATH} + export CLASSPATH + ``` + + c) Copy back the modified setDomainEnv.sh to the pod. + ```bash + $ kubectl cp setDomainEnv.sh wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/bin/setDomainEnv.sh + ``` + +1. Create configuration file for the WebLogic Logging Exporter. +Copy WebLogicLoggingExporter.yaml to the domain folder in the WebLogic server pod. YAML specifies the elasticsearch server host and port number. + ```bash + $ kubectl cp WebLogicLoggingExporter.yaml wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/config/ + ``` + +1. Restart WebLogic Servers + + Now we can restart the WebLogic servers for the weblogic-logging-exporter to get loaded in the servers. + + To restart the servers, use stopDomain.sh and startDomain.sh scripts from https://github.com/oracle/weblogic-kubernetes-operator/tree/master/kubernetes/samples/scripts/domain-lifecycle + + The stopDomain.sh script shuts down a domain by patching the `spec.serverStartPolicy` attribute of the domain resource to `NEVER`. The operator will shut down the WebLogic Server instance Pods that are part of the domain after the `spec.serverStartPolicy` attribute is updated to `NEVER`. See the script usage information by using the -h option. + + ```bash + $ stopDomain.sh -d wcp-domain -n wcpns + ``` + Sample output: + ```bash + [INFO] Patching domain 'wcp-domain' in namespace 'wcpns' from serverStartPolicy='IF_NEEDED' to 'NEVER'. + domain.weblogic.oracle/wcp-domain patched + [INFO] Successfully patched domain 'wcp-domain' in namespace 'wcpns' with 'NEVER' start policy! + ``` + + Verify servers by checking the pod status. + ```bash + $ kubectl get pods -n wcpns + ``` + + After all the servers are shutdown, run startDomain.sh script to start again. + + The startDomain.sh script starts a deployed domain by patching the `spec.serverStartPolicy` attribute of the domain resource to `IF_NEEDED`. The operator will start the WebLogic Server instance Pods that are part of the domain after the `spec.serverStartPolicy` attribute of the domain resource is updated to `IF_NEEDED`. See the script usage information by using the -h option. + + ```bash + $ startDomain.sh -d wcp-domain -n wcpns + ``` + Sample output: + ```bash + [INFO] Patching domain 'wcp-domain' from serverStartPolicy='NEVER' to 'IF_NEEDED'. + domain.weblogic.oracle/wcp-domain patched + [INFO] Successfully patched domain 'wcp-domain' in namespace 'wcpns' with 'IF_NEEDED' start policy! + ``` + + Verify servers by checking the pod status. Pod status will be RUNNING. + ```bash + $ kubectl get pods -n wcpns + ``` + In the server logs, you will be able to see the weblogic-logging-exporter class being called. + +1. Create an index pattern in Kibana + + We need to create an index pattern in Kibana for the logs to be available in the dashboard. + + Create an index pattern `wls*` in `Kibana` > `Management`. After the server starts, you will be able to see the log data from the WebLogic servers in the Kibana dashboard, + diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml b/OracleWebCenterPortal/kubernetes/logging-services/weblogic-logging-exporter/WebLogicLoggingExporter.yaml old mode 100755 new mode 100644 similarity index 61% rename from OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml rename to OracleWebCenterPortal/kubernetes/logging-services/weblogic-logging-exporter/WebLogicLoggingExporter.yaml index 5c9e711f9..5ba6bf454 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml +++ b/OracleWebCenterPortal/kubernetes/logging-services/weblogic-logging-exporter/WebLogicLoggingExporter.yaml @@ -1,9 +1,13 @@ # Copyright (c) 2021, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + weblogicLoggingIndexName: wls -publishHost: elasticsearch.wcpns.svc.cluster.local -publishPort: 9600 +publishHost: elasticsearch.default.svc.cluster.local +publishPort: 9200 domainUID: wcp-domain -weblogicLoggingExporterEnabled: true -weblogicLoggingExporterSeverity: TRACE +weblogicLoggingExporterEnabled: true +weblogicLoggingExporterSeverity: Notice weblogicLoggingExporterBulkSize: 1 + + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/README.md b/OracleWebCenterPortal/kubernetes/monitoring-service/README.md new file mode 100644 index 000000000..23a1c20c9 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/README.md @@ -0,0 +1,276 @@ +# Monitor the OracleWebCenterPortal instance using Prometheus and Grafana +Using the `WebLogic Monitoring Exporter` you can scrape runtime information from a running OracleWebCenterPortal instance and monitor them using Prometheus and Grafana. + +## Prerequisites + +- Have Docker and a Kubernetes cluster running and have `kubectl` installed and configured. +- Have Helm installed. +- An OracleWebCenterPortal domain deployed by `weblogic-operator` is running in the Kubernetes cluster. + +## Set up monitoring for OracleWebCenterPortal domain + +Set up the WebLogic Monitoring Exporter that will collect WebLogic Server metrics and monitor OracleWebCenterPortal domain. + +**Note**: Either of the following methods can be used to set up monitoring for OracleWebCenterPortal domain. Using `setup-monitoring.sh` does the set up in an automated way. + +1. [Set up manually](#set-up-manually) +1. [Set up using `setup-monitoring.sh`](#set-up-using-setup-monitoringsh) + +## Set up manually + +### Deploy Prometheus and Grafana + +Refer to the compatibility matrix of [Kube Prometheus](https://github.com/coreos/kube-prometheus#kubernetes-compatibility-matrix) and clone the [release](https://github.com/coreos/kube-prometheus/releases) version of the `kube-prometheus` repository according to the Kubernetes version of your cluster. + +1. Clone the `kube-prometheus` repository: + ``` + $ git clone https://github.com/coreos/kube-prometheus.git + ``` + +1. Change to folder `kube-prometheus` and enter the following commands to create the namespace and CRDs, and then wait for their availability before creating the remaining resources: + + ``` + $ cd kube-prometheus + $ kubectl create -f manifests/setup + $ until kubectl get servicemonitors --all-namespaces ; do date; sleep 1; echo ""; done + $ kubectl create -f manifests/ + ``` + +1. `kube-prometheus` requires all nodes in the Kubernetes cluster to be labeled with `kubernetes.io/os=linux`. If any node is not labeled with this, then you need to label it using the following command: + + ``` + $ kubectl label nodes --all kubernetes.io/os=linux + ``` + +1. Enter the following commands to provide external access for Grafana, Prometheus, and Alertmanager: + + ``` + $ kubectl patch svc grafana -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32100 }]' + + $ kubectl patch svc prometheus-k8s -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32101 }]' + + $ kubectl patch svc alertmanager-main -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32102 }]' + ``` + + Note: + * `32100` is the external port for Grafana + * `32101` is the external port for Prometheus + * `32102` is the external port for Alertmanager + +### Generate the WebLogic Monitoring Exporter Deployment Package + +The `wls-exporter.war` package need to be updated and created for each listening ports (Administration Server and Managed Servers) in the domain. +Set the below environment values based on your environment and run the script `get-wls-exporter.sh` to generate the required WAR files at `${WORKDIR}/monitoring-service/scripts/wls-exporter-deploy`: +- adminServerPort +- wlsMonitoringExporterTowcpCluster +- wcpManagedServerPort +- wlsMonitoringExporterTowcpPortletCluster +- wcpPortletManagedServerPort + +For example: + +``` +$ cd ${WORKDIR}/monitoring-service/scripts +$ export adminServerPort=7001 +$ export wlsMonitoringExporterTowcpCluster=true +$ export wcpManagedServerPort=8888 +$ export wlsMonitoringExporterTowcpPortletCluster=true +$ export wcpPortletManagedServerPort=8889 +$ sh get-wls-exporter.sh +``` + +Verify whether the required WAR files are generated at `${WORKDIR}/monitoring-service/scripts/wls-exporter-deploy`. + +``` +$ ls ${WORKDIR}/monitoring-service/scripts/wls-exporter-deploy +``` + +### Deploy the WebLogic Monitoring Exporter into the OracleWebCenterPortal domain + +Follow these steps to copy and deploy the WebLogic Monitoring Exporter WAR files into the OracleWebCenterPortal Domain. + +**Note**: Replace the `` with appropriate values based on your environment: + +``` +$ cd ${WORKDIR}/monitoring-service/scripts +$ kubectl cp wls-exporter-deploy /:/u01/oracle +$ kubectl cp deploy-weblogic-monitoring-exporter.py /:/u01/oracle/wls-exporter-deploy +$ kubectl exec -it -n -- /u01/oracle/oracle_common/common/bin/wlst.sh /u01/oracle/wls-exporter-deploy/deploy-weblogic-monitoring-exporter.py \ +-domainName -adminServerName -adminURL \ +-wcpClusterName -wlsMonitoringExporterTowcpCluster \ +-wcpPortletClusterName -wlsMonitoringExporterTowcpPortletCluster \ +-username -password +``` + +For example: + +``` +$ cd ${WORKDIR}/monitoring-service/scripts +$ kubectl cp wls-exporter-deploy wcpns/wcp-domain-adminserver:/u01/oracle +$ kubectl cp deploy-weblogic-monitoring-exporter.py wcpns/wcp-domain-adminserver:/u01/oracle/wls-exporter-deploy +$ kubectl exec -it -n wcpns wcp-domain-adminserver -- /u01/oracle/oracle_common/common/bin/wlst.sh /u01/oracle/wls-exporter-deploy/deploy-weblogic-monitoring-exporter.py \ +-domainName wcp-domain -adminServerName -adminserver:7001 \ +-wcpClusterName wcp-cluster -wlsMonitoringExporterTowcpCluster true \ +-wcpPortletClusterName wcportlet-cluster -wlsMonitoringExporterTowcpPortletCluster true \ +-username weblogic -password Welcome1 +``` + +### Configure Prometheus Operator + +Prometheus enables you to collect metrics from the WebLogic Monitoring Exporter. The Prometheus Operator identifies the targets using service discovery. To get the WebLogic Monitoring Exporter end point discovered as a target, you must create a service monitor pointing to the service. + +The service monitor deployment YAML configuration file is available at `${WORKDIR}/monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml.template`. Copy the file as `wls-exporter-ServiceMonitor.yaml` to update with appropriate values as detailed below. + +The exporting of metrics from `wls-exporter` requires `basicAuth`, so a Kubernetes `Secret` is created with the user name and password that are base64 encoded. This `Secret` is used in the `ServiceMonitor` deployment. The `wls-exporter-ServiceMonitor.yaml` has namespace as `wcpns` and has `basicAuth` with credentials as `username: %USERNAME%` and `password: %PASSWORD%`. Update `%USERNAME%` and `%PASSWORD% ` in base64 encoded and all occurences of `wcpns` based on your environment. + +Use the following example for base64 encoded: + +``` +$ echo -n "Welcome1" | base64 +V2VsY29tZTE= +``` + +You need to add `RoleBinding` and `Role` for the namespace (wcpns) under which the WebLogic Servers pods are running in the Kubernetes cluster. These are required for Prometheus to access the endpoints provided by the WebLogic Monitoring Exporters. The YAML configuration files for wcpns namespace are provided in "${WORKDIR}/monitoring-service/manifests/". + +If you are using namespace other than `wcpns`, update the namespace details in `prometheus-roleBinding-domain-namespace.yaml` and `prometheus-roleSpecific-domain-namespace.yaml`. + +Perform the below steps for enabling Prometheus to collect the metrics from the WebLogic Monitoring Exporter: + +``` +$ cd ${WORKDIR}/monitoring-service/manifests +$ kubectl apply -f . +``` + +### Verify the service discovery of WebLogic Monitoring Exporter + +After the deployment of the service monitor, Prometheus should be able to discover wls-exporter and collect the metrics. + +1. Access the Prometheus dashboard at `http://mycompany.com:32101/` + +1. Navigate to **Status** to see the **Service Discovery** details. + +1. Verify that `wls-exporter` is listed in the discovered Services. + + +### Deploy Grafana Dashboard + +You can access the Grafana dashboard at `http://mycompany.com:32100/`. + +1. Log in to Grafana dashboard with username: admin and password: admin`. + +1. Navigate to + (Create) -> Import -> Upload the `weblogic-server-dashboard-import.json` file (provided at `${WORKDIR}/monitoring-service/config/weblogic-server-dashboard-import.json`). + + +## Set up using `setup-monitoring.sh` + +Alternatively, you can run the helper script `setup-monitoring.sh` available at `${WORKDIR}/monitoring-service` to setup the monitoring for OracleWebCenterPortal domain. + +This script creates kube-prometheus-stack(Prometheus, Grafana and Alertmanager), WebLogic Monitoring Exporter and imports `weblogic-server-dashboard.json` into Grafana for WebLogic Server Dashboard. + +### Prepare to use the setup monitoring script + +The sample scripts for setup monitoring for OracleWebCenterPortal domain are available at `${WORKDIR}/monitoring-service`. + +You must edit `monitoring-inputs.yaml`(or a copy of it) to provide the details of your domain. Refer to the configuration parameters below to understand the information that you must provide in this file. + +#### Configuration parameters + +The following parameters can be provided in the inputs file. + +| Parameter | Description | Default | +| --- | --- | --- | +| `domainUID` | domainUID of the OracleWebCenterPortal domain. | `wcp-domain` | +| `domainNamespace` | Kubernetes namespace of the OracleWebCenterPortal domain. | `wcpns` | +| `setupKubePrometheusStack` | Boolean value indicating whether kube-prometheus-stack (Prometheus, Grafana and Alertmanager) to be installed | `true` | +| `additionalParamForKubePrometheusStack` | The script install's kube-prometheus-stack with `service.type` as NodePort and values for `service.nodePort` as per the parameters defined in `monitoring-inputs.yaml`. Use `additionalParamForKubePrometheusStack` parameter to further configure with additional parameters as per [values.yaml](https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/values.yaml). Sample value to disable NodeExporter, Prometheus-Operator TLS support and Admission webhook support for PrometheusRules resources is `--set nodeExporter.enabled=false --set prometheusOperator.tls.enabled=false --set prometheusOperator.admissionWebhooks.enabled=false`| | +| `monitoringNamespace` | Kubernetes namespace for monitoring setup. | `monitoring` | +| `adminServerName` | Name of the Administration Server. | `AdminServer` | +| `adminServerPort` | Port number for the Administration Server inside the Kubernetes cluster. | `7001` | +| `wcpClusterName` | Name of the wcpCluster. | `wcp-cluster` | +| `wcpManagedServerPort` | Port number of the managed servers in the wcpCluster. | `8888` | +| `wlsMonitoringExporterTowcpCluster` | Boolean value indicating whether to deploy WebLogic Monitoring Exporter to wcpCluster. | `false` | +| `wcpPortletClusterName` | Name of the wcpPortletCluster. | `wcportlet-cluster` | +| `wcpPortletManagedServerPort` | Port number of the managed servers in the wcpPortletCluster. | `8889` | +| `wlsMonitoringExporterTowcpPortletCluster` | Boolean value indicating whether to deploy WebLogic Monitoring Exporter to wcpPortletCluster. | `false` | +| `exposeMonitoringNodePort` | Boolean value indicating if the Monitoring Services (Prometheus, Grafana and Alertmanager) is exposed outside of the Kubernetes cluster. | `false` | +| `prometheusNodePort` | Port number of the Prometheus outside the Kubernetes cluster. | `32101` | +| `grafanaNodePort` | Port number of the Grafana outside the Kubernetes cluster. | `32100` | +| `alertmanagerNodePort` | Port number of the Alertmanager outside the Kubernetes cluster. | `32102` | +| `weblogicCredentialsSecretName` | Name of the Kubernetes secret which has Administration Server’s user name and password. | `wcp-domain-domain-credentials` | + +Note that the values specified in the `monitoring-inputs.yaml` file will be used to install kube-prometheus-stack (Prometheus, Grafana and Alertmanager) and deploying WebLogic Monitoring Exporter into the OracleWebCenterPortal domain. Hence make the domain specific values to be same as that used during domain creation. + +### Run the setup monitoring script + +Update the values in `monitoring-inputs.yaml` as per your requirement and run the `setup-monitoring.sh` script, specifying your inputs file: + +```bash +$ cd ${WORKDIR}/monitoring-service +$ ./setup-monitoring.sh \ + -i monitoring-inputs.yaml +``` +The script will perform the following steps: + +- Helm install `prometheus-community/kube-prometheus-stack` of version "16.5.0" if `setupKubePrometheusStack` is set to `true`. +- Deploys WebLogic Monitoring Exporter to Administration Server. +- Deploys WebLogic Monitoring Exporter to `wcpCluster` if `wlsMonitoringExporterTowcpCluster` is set to `true`. +- Deploys WebLogic Monitoring Exporter to `wcpPortletCluster` if `wlsMonitoringExporterTowcpPortletCluster` is set to `true`. +- Exposes the Monitoring Services (Prometheus at `32101`, Grafana at `32100` and Alertmanager at `32102`) outside of the Kubernetes cluster if `exposeMonitoringNodePort` is set to `true`. +- Imports the WebLogic Server Grafana Dashboard if `setupKubePrometheusStack` is set to `true`. + +### Verify the results +The setup monitoring script will report failure if there was any error. However, verify that required resources were created by the script. + +#### Verify the kube-prometheus-stack + +To confirm that `prometheus-community/kube-prometheus-stack` was installed when `setupKubePrometheusStack` is set to `true`, run the following command: + +```bash +$ helm ls -n +``` +Replace with value for Kubernetes namespace used for monitoring. + +Sample output: +```bash +$ helm ls -n monitoring +NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION +monitoring monitoring 1 2021-06-18 12:58:35.177221969 +0000 UTC deployed kube-prometheus-stack-16.5.0 0.48.0 +$ +``` + +#### Verify the Prometheus, Grafana and Alertmanager setup + +When `exposeMonitoringNodePort` was set to `true`, verify that monitoring services are accessible outside of the Kubernetes cluster: + +- `32100` is the external port for Grafana and with credentials `admin:admin` +- `32101` is the external port for Prometheus +- `32102` is the external port for Alertmanager + +#### Verify the service discovery of WebLogic Monitoring Exporter + +Verify whether prometheus is able to discover wls-exporter and collect the metrics: + +1. Access the Prometheus dashboard at http://mycompany.com:32101/ + +1. Navigate to Status to see the Service Discovery details. + +1. Verify that wls-exporter is listed in the discovered services. + +#### Verify the WebLogic Server dashoard + +You can access the Grafana dashboard at http://mycompany.com:32100/. + +1. Log in to Grafana dashboard with username: `admin` and password: `admin`. + +1. Navigate to "WebLogic Server Dashboard" under General and verify. + +### Delete the monitoring setup + +To delete the monitoring setup created by [Run the setup monitoring script](#run-the-setup-monitoring-script), run the below command: + +```bash +$ cd ${WORKDIR}/monitoring-service +$ ./delete-monitoring.sh \ + -i monitoring-inputs.yaml +``` + diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_as.yml b/OracleWebCenterPortal/kubernetes/monitoring-service/config/config.yml.template old mode 100755 new mode 100644 similarity index 98% rename from OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_as.yml rename to OracleWebCenterPortal/kubernetes/monitoring-service/config/config.yml.template index df8248388..792f64d27 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/config_as.yml +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/config/config.yml.template @@ -1,8 +1,8 @@ # Copyright (c) 2021, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - +# metricsNameSnakeCase: true -restPort: 7001 +restPort: %PORT% queries: - key: name keyName: location @@ -18,26 +18,26 @@ queries: servlets: prefix: wls_servlet_ key: servletName - + - JVMRuntime: prefix: wls_jvm_ key: name - + - executeQueueRuntimes: prefix: wls_socketmuxer_ key: name values: [pendingRequestCurrentCount] - + - workManagerRuntimes: prefix: wls_workmanager_ key: name values: [stuckThreadCount, pendingRequests, completedRequests] - + - threadPoolRuntime: prefix: wls_threadpool_ key: name values: [executeThreadTotalCount, queueLength, stuckThreadCount, hoggingThreadCount] - + - JMSRuntime: key: name keyName: jmsruntime @@ -50,7 +50,7 @@ queries: prefix: wls_jms_dest_ key: name keyName: destination - + - persistentStoreRuntimes: prefix: wls_persistentstore_ key: name @@ -61,3 +61,4 @@ queries: - JTARuntime: prefix: wls_jta_ key: name + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic-server-dashboard-import.json b/OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic-server-dashboard-import.json new file mode 100644 index 000000000..c2fa9e2eb --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic-server-dashboard-import.json @@ -0,0 +1,3312 @@ +{ + "__inputs": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "5.2.4" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "5.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1563266678971, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 32, + "panels": [], + "title": "Servers", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 13, + "x": 0, + "y": 1 + }, + "hideTimeOverride": true, + "id": 16, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(count (wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"}) by (name))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Running Servers", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 11, + "x": 13, + "y": 1 + }, + "id": 23, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(count(wls_webapp_config_deployment_state{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"}) by (app))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Deployed Applications", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "hideTimeOverride": true, + "id": 104, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "weblogic_serverName", + "targets": [ + { + "expr": "wls_server_activation_time{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\",weblogic_serverName=\"$serverName\"}", + "format": "table", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Server Name", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#56A64B", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 6, + "y": 4 + }, + "id": 84, + "interval": "", + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "wls_server_state_val{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Server Status", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "SHUTDOWN", + "value": "0" + }, + { + "op": "=", + "text": "STARTING", + "value": "1" + }, + { + "op": "=", + "text": "RUNNING", + "value": "2" + }, + { + "op": "=", + "text": "STANDBY", + "value": "3" + }, + { + "op": "=", + "text": "FAILED", + "value": "8" + }, + { + "op": "=", + "text": "FAILED", + "value": "17" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 10, + "y": 4 + }, + "hideTimeOverride": true, + "id": 27, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "100 - wls_jvm_heap_free_percent{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Heap Usage", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 14, + "y": 4 + }, + "hideTimeOverride": true, + "id": 91, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Running Time", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "description": "", + "format": "short", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 19, + "y": 4 + }, + "hideTimeOverride": true, + "id": 96, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "wls_server_open_sockets_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Open Sockets", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "aliasColors": { + " heap free managed-server-1": "super-light-green", + " heap free managed-server-2": "dark-green", + "heap size managed-server-1 ": "super-light-red", + "heap size managed-server-2 ": "dark-red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_jvm_heap_free_current{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " Heap Free ()", + "refId": "B" + }, + { + "expr": "wls_jvm_heap_size_current{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "Heap Size ()", + "refId": "A" + }, + { + "expr": "wls_jvm_heap_size_max{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "Heap Max ()", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JVM Heap", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + " heap free managed-server-1": "super-light-green", + " heap free managed-server-2": "dark-green", + "heap size managed-server-1 ": "super-light-red", + "heap size managed-server-2 ": "dark-red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 21, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_jvm_process_cpu_load{weblogic_domainUID=~\"$domainName\", weblogic_clusterName=~\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"} * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " ", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Load", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_threadpool_execute_thread_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total Threads ()", + "refId": "A" + }, + { + "expr": "wls_threadpool_stuck_thread_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Stuck Threads ()", + "refId": "D" + }, + { + "expr": "wls_threadpool_queue_length{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "queue", + "refId": "C" + }, + { + "expr": "wls_threadpool_hogging_thread_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "hogging", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Thread Pool", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 35, + "panels": [ + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 28 + }, + "hideTimeOverride": true, + "id": 126, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Sessions", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_webapp_config_sessions_opened_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Sessions (top $topN)", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 28 + }, + "hideTimeOverride": true, + "id": 136, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Requests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_servlet_invocation_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Requests (top $topN)", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 28 + }, + "hideTimeOverride": true, + "id": 134, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Time", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "ms" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_servlet_execution_time_total{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Execution Time (top $topN)", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_webapp_config_open_sessions_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + }, + { + "expr": "", + "format": "time_series", + "intervalFactor": 1, + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Current Sessions ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 128, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": " sum(irate(wls_webapp_config_sessions_opened_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (app)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Session Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 132, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(wls_servlet_execution_time_average{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app)) / (count(wls_servlet_execution_time_average{weblogic_domainUID=\"domain1\", weblogic_clusterName=\"cluster-1\"}) by (app))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Execution Time per Request ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 138, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_servlet_invocation_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (app)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Request Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Web Applications", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 43, + "panels": [ + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 29 + }, + "hideTimeOverride": true, + "id": 111, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Server", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "weblogic_serverName", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Name", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "name", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Active Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Current Capacity", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_datasource_curr_capacity{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "C" + }, + { + "expr": "sum(wls_datasource_active_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_datasource_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Overview", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 13, + "x": 0, + "y": 33 + }, + "id": 50, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_active_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " @ ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 11, + "x": 13, + "y": 33 + }, + "id": 71, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(wls_datasource_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " @ ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connection Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 9, + "w": 11, + "x": 0, + "y": 41 + }, + "id": 46, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_waiting_for_connection_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " @ ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pending Connection Requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 9, + "w": 13, + "x": 11, + "y": 41 + }, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_connection_delay_time{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " @ ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average Connection Delay Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Data Sources", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 40, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 145, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jmsruntime_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JMS Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 147, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jmsruntime_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (weblogic_serverName)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JMS Connection Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 36 + }, + "hideTimeOverride": true, + "id": 113, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Name", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "jmsserver", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Current Dests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Total Dests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_jms_destinations_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + }, + { + "expr": "sum(wls_jms_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_jms_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "sum(wls_jms_destinations_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "E" + }, + { + "expr": "sum(wls_jms_destinations_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "F" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "JMSServer Overview", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 54, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jms_messages_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Current ()", + "refId": "A" + }, + { + "expr": "sum(wls_jms_messages_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pending ()", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Messages", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 56, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jms_bytes_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Current ()", + "refId": "A" + }, + { + "expr": "sum(wls_jms_bytes_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pending ()", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bytes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 58, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jms_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Message Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 117, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jms_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Byte Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 54 + }, + "hideTimeOverride": true, + "id": 119, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 3, + "desc": false + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Destination", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "destination", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Current Consumers", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Current Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Pending Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Currrent Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Pending Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #F", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #G", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_jms_dest_consumers_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_jms_dest_messages_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + }, + { + "expr": "sum(wls_jms_dest_messages_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "C" + }, + { + "expr": "sum(wls_jms_dest_bytes_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "sum(wls_jms_dest_bytes_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "E" + }, + { + "expr": "sum(wls_jms_dest_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(wls_jms_dest_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "G" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Destinations Overview", + "transform": "table", + "type": "table" + } + ], + "title": "JMS Services", + "type": "row" + } + ], + "refresh": false, + "schemaVersion": 16, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "prometheus", + "value": "prometheus" + }, + "hide": 0, + "label": null, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "Domain", + "multi": false, + "name": "domainName", + "options": [], + "query": "label_values(weblogic_domainUID)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "Cluster", + "multi": false, + "name": "clusterName", + "options": [], + "query": "label_values(wls_jvm_uptime{weblogic_domainUID=\"$domainName\"},weblogic_clusterName)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": "Server", + "multi": true, + "name": "serverName", + "options": [], + "query": "label_values(wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"},weblogic_serverName)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "tags": [], + "text": "5", + "value": "5" + }, + "hide": 0, + "includeAll": false, + "label": "Top N", + "multi": false, + "name": "topN", + "options": [ + { + "selected": false, + "text": "3", + "value": "3" + }, + { + "selected": true, + "text": "5", + "value": "5" + }, + { + "selected": false, + "text": "7", + "value": "7" + }, + { + "selected": false, + "text": "10", + "value": "10" + } + ], + "query": "3, 5, 7, 10", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "hidden": false, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "WebLogic Server Dashboard", + "uid": "5yUwzbZWz", + "version": 6 +} diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic-server-dashboard.json b/OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic-server-dashboard.json new file mode 100644 index 000000000..cf6d5f776 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic-server-dashboard.json @@ -0,0 +1,3315 @@ +{ + "dashboard": { + "__inputs": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "5.2.4" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "5.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1563266678971, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 32, + "panels": [], + "title": "Servers", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 13, + "x": 0, + "y": 1 + }, + "hideTimeOverride": true, + "id": 16, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(count (wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"}) by (name))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Running Servers", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 11, + "x": 13, + "y": 1 + }, + "id": 23, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(count(wls_webapp_config_deployment_state{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"}) by (app))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Deployed Applications", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "hideTimeOverride": true, + "id": 104, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "weblogic_serverName", + "targets": [ + { + "expr": "wls_server_activation_time{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\",weblogic_serverName=\"$serverName\"}", + "format": "table", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Server Name", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#56A64B", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 6, + "y": 4 + }, + "id": 84, + "interval": "", + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "wls_server_state_val{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Server Status", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "SHUTDOWN", + "value": "0" + }, + { + "op": "=", + "text": "STARTING", + "value": "1" + }, + { + "op": "=", + "text": "RUNNING", + "value": "2" + }, + { + "op": "=", + "text": "STANDBY", + "value": "3" + }, + { + "op": "=", + "text": "FAILED", + "value": "8" + }, + { + "op": "=", + "text": "FAILED", + "value": "17" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 10, + "y": 4 + }, + "hideTimeOverride": true, + "id": 27, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "100 - wls_jvm_heap_free_percent{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Heap Usage", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 1, + "description": "", + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 14, + "y": 4 + }, + "hideTimeOverride": true, + "id": 91, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Running Time", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "description": "", + "format": "short", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 19, + "y": 4 + }, + "hideTimeOverride": true, + "id": 96, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "repeat": "serverName", + "repeatDirection": "v", + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "instance", + "targets": [ + { + "expr": "wls_server_open_sockets_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=\"$serverName\"}", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "50,80", + "timeFrom": null, + "timeShift": null, + "title": "Open Sockets", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "" + } + ], + "valueName": "current" + }, + { + "aliasColors": { + " heap free managed-server-1": "super-light-green", + " heap free managed-server-2": "dark-green", + "heap size managed-server-1 ": "super-light-red", + "heap size managed-server-2 ": "dark-red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_jvm_heap_free_current{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " Heap Free ()", + "refId": "B" + }, + { + "expr": "wls_jvm_heap_size_current{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "Heap Size ()", + "refId": "A" + }, + { + "expr": "wls_jvm_heap_size_max{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "Heap Max ()", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JVM Heap", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + " heap free managed-server-1": "super-light-green", + " heap free managed-server-2": "dark-green", + "heap size managed-server-1 ": "super-light-red", + "heap size managed-server-2 ": "dark-red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 21, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_jvm_process_cpu_load{weblogic_domainUID=~\"$domainName\", weblogic_clusterName=~\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"} * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " ", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Load", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_threadpool_execute_thread_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total Threads ()", + "refId": "A" + }, + { + "expr": "wls_threadpool_stuck_thread_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Stuck Threads ()", + "refId": "D" + }, + { + "expr": "wls_threadpool_queue_length{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "queue", + "refId": "C" + }, + { + "expr": "wls_threadpool_hogging_thread_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "hogging", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Thread Pool", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 35, + "panels": [ + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 28 + }, + "hideTimeOverride": true, + "id": 126, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Sessions", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_webapp_config_sessions_opened_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Sessions (top $topN)", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 28 + }, + "hideTimeOverride": true, + "id": 136, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Requests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_servlet_invocation_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Requests (top $topN)", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 28 + }, + "hideTimeOverride": true, + "id": 134, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Webapp", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "app", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Total Time", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "ms" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topN,sum(wls_servlet_execution_time_total{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Execution Time (top $topN)", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_webapp_config_open_sessions_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + }, + { + "expr": "", + "format": "time_series", + "intervalFactor": 1, + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Current Sessions ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 128, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": " sum(irate(wls_webapp_config_sessions_opened_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (app)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Session Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 132, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(wls_servlet_execution_time_average{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (app)) / (count(wls_servlet_execution_time_average{weblogic_domainUID=\"domain1\", weblogic_clusterName=\"cluster-1\"}) by (app))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Execution Time per Request ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 138, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_servlet_invocation_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (app)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Request Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Web Applications", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 43, + "panels": [ + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 29 + }, + "hideTimeOverride": true, + "id": 111, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Server", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "weblogic_serverName", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Name", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "name", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Active Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Current Capacity", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Connections", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_datasource_curr_capacity{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "C" + }, + { + "expr": "sum(wls_datasource_active_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_datasource_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName,name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Overview", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 13, + "x": 0, + "y": 33 + }, + "id": 50, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_active_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " @ ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 8, + "w": 11, + "x": 13, + "y": 33 + }, + "id": 71, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(wls_datasource_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " @ ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connection Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "per second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 9, + "w": 11, + "x": 0, + "y": 41 + }, + "id": 46, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_waiting_for_connection_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " @ ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pending Connection Requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 9, + "w": 13, + "x": 11, + "y": 41 + }, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "wls_datasource_connection_delay_time{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " @ ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average Connection Delay Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Data Sources", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 40, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 145, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jmsruntime_connections_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (weblogic_serverName)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JMS Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 147, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jmsruntime_connections_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (weblogic_serverName)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JMS Connection Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 36 + }, + "hideTimeOverride": true, + "id": 113, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Name", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "jmsserver", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Current Dests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Total Dests", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_jms_destinations_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + }, + { + "expr": "sum(wls_jms_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_jms_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "sum(wls_jms_destinations_total_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "E" + }, + { + "expr": "sum(wls_jms_destinations_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "F" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "JMSServer Overview", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 54, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jms_messages_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Current ()", + "refId": "A" + }, + { + "expr": "sum(wls_jms_messages_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pending ()", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Messages", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 56, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(wls_jms_bytes_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Current ()", + "refId": "A" + }, + { + "expr": "sum(wls_jms_bytes_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pending ()", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bytes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 58, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jms_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Message Rate ", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 117, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(wls_jms_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}[5m])) by (jmsserver)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Byte Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 54 + }, + "hideTimeOverride": true, + "id": 119, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 3, + "desc": false + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Destination", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "destination", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Current Consumers", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Current Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Pending Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Currrent Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Pending Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Msgs", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #F", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Total Bytes", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #G", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(wls_jms_dest_consumers_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(wls_jms_dest_messages_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + }, + { + "expr": "sum(wls_jms_dest_messages_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "C" + }, + { + "expr": "sum(wls_jms_dest_bytes_current_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "sum(wls_jms_dest_bytes_pending_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "E" + }, + { + "expr": "sum(wls_jms_dest_messages_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(wls_jms_dest_bytes_received_count{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\", weblogic_serverName=~\"${serverName:regex}\"}) by (destination)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "G" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Destinations Overview", + "transform": "table", + "type": "table" + } + ], + "title": "JMS Services", + "type": "row" + } + ], + "refresh": false, + "schemaVersion": 16, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "prometheus", + "value": "prometheus" + }, + "hide": 0, + "label": null, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "Domain", + "multi": false, + "name": "domainName", + "options": [], + "query": "label_values(weblogic_domainUID)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "Cluster", + "multi": false, + "name": "clusterName", + "options": [], + "query": "label_values(wls_jvm_uptime{weblogic_domainUID=\"$domainName\"},weblogic_clusterName)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": "Server", + "multi": true, + "name": "serverName", + "options": [], + "query": "label_values(wls_jvm_uptime{weblogic_domainUID=\"$domainName\", weblogic_clusterName=\"$clusterName\"},weblogic_serverName)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "tags": [], + "text": "5", + "value": "5" + }, + "hide": 0, + "includeAll": false, + "label": "Top N", + "multi": false, + "name": "topN", + "options": [ + { + "selected": false, + "text": "3", + "value": "3" + }, + { + "selected": true, + "text": "5", + "value": "5" + }, + { + "selected": false, + "text": "7", + "value": "7" + }, + { + "selected": false, + "text": "10", + "value": "10" + } + ], + "query": "3, 5, 7, 10", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "hidden": false, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "WebLogic Server Dashboard", + "uid": "5yUwzbZWz", + "version": 6 + } +} + diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/weblogic.xml b/OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic.xml old mode 100755 new mode 100644 similarity index 100% rename from OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/config/weblogic.xml rename to OracleWebCenterPortal/kubernetes/monitoring-service/config/weblogic.xml diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/delete-monitoring.sh b/OracleWebCenterPortal/kubernetes/monitoring-service/delete-monitoring.sh new file mode 100644 index 000000000..eee881c77 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/delete-monitoring.sh @@ -0,0 +1,122 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# delete-monitoring.sh + +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +OLD_PWD=`pwd` + + +# +## Function to exit and print an error message +## $1 - text of message +function fail { + printError $* + exit 1 +} + +# Function to print an error message +function removeFileIfExists { + echo "input is $1" + if [ -f $1 ]; then + rm -f $1 + fi +} + +function exitIfError { + if [ "$1" != "0" ]; then + echo "$2" + exit $1 + fi +} +# +# Function to parse a yaml file and generate the bash exports +# $1 - Input filename +# $2 - Output filename +function parseYaml { + local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') + sed -ne "s|^\($s\):|\1|" \ + -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | + awk -F$fs '{ + if (length($3) > 0) { + # javaOptions may contain tokens that are not allowed in export command + # we need to handle it differently. + if ($2=="javaOptions") { + printf("%s=%s\n", $2, $3); + } else { + printf("export %s=\"%s\"\n", $2, $3); + } + } + }' > $2 +} + +function usage { + echo usage: ${script} -i file [-v] [-h] + echo " -i Parameter inputs file, must be specified." + echo " -h Help" + exit $1 +} + + +function deletePrometheusGrafana { + helm delete ${monitoringNamespace} --namespace ${monitoringNamespace} +} + +#Parse the inputs +while getopts "hi:" opt; do + case $opt in + i) valuesInputFile="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${valuesInputFile} ]; then + echo "${script}: -i must be specified." + missingRequiredOption="true" +fi + +if [ "${missingRequiredOption}" == "true" ]; then + usage 1 +fi + +if [ ! -f ${valuesInputFile} ]; then + echo "Unable to locate the input parameters file ${valuesInputFile}" + fail 'The error listed above must be resolved before the script can continue' +fi + +exportValuesFile=$(mktemp /tmp/export-values-XXXXXXXXX.sh) +parseYaml ${valuesInputFile} ${exportValuesFile} + + +source ${exportValuesFile} +rm ${exportValuesFile} + +# Setting up the WebLogic Monitoring Exporter + +echo "Undeploy WebLogic Monitoring Exporter started" +serviceMonitor=${scriptDir}/manifests/wls-exporter-ServiceMonitor.yaml +kubectl delete --ignore-not-found=true -f ${serviceMonitor} +script=${scriptDir}/scripts/undeploy-weblogic-monitoring-exporter.sh +sh ${script} +if [ "$?" != "0" ]; then + echo "ERROR: $script failed." + echo "Undeploy WebLogic Monitoring Exporter completed with errors. Review the logs and rerun" +else + echo "Undeploy WebLogic Monitoring Exporter completed." +fi + +if [ "${setupKubePrometheusStack}" = "true" ]; then + echo "Deleting Prometheus and grafana started" + deletePrometheusGrafana + echo "Deleting Prometheus and grafana completed" +fi +cd $OLD_PWD + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/prometheus-roleBinding-domain-namespace.yaml b/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/prometheus-roleBinding-domain-namespace.yaml new file mode 100644 index 000000000..98e23c3ea --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/prometheus-roleBinding-domain-namespace.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +apiVersion: rbac.authorization.k8s.io/v1 +items: +- apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: prometheus-k8s + namespace: wcpns + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: prometheus-k8s + subjects: + - kind: ServiceAccount + name: prometheus-k8s + namespace: monitoring +kind: RoleBindingList + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/prometheus-roleSpecific-domain-namespace.yaml b/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/prometheus-roleSpecific-domain-namespace.yaml new file mode 100644 index 000000000..aab147753 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/prometheus-roleSpecific-domain-namespace.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +apiVersion: rbac.authorization.k8s.io/v1 +items: +- apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: prometheus-k8s + namespace: wcpns + rules: + - apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch +kind: RoleList + diff --git a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml b/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml old mode 100755 new mode 100644 similarity index 90% rename from OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml rename to OracleWebCenterPortal/kubernetes/monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml index 075afa320..0d54521e7 --- a/OracleWebCenterPortal/kubernetes/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml @@ -1,20 +1,20 @@ # Copyright (c) 2021, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. - +# apiVersion: v1 kind: Secret metadata: name: basic-auth namespace: monitoring data: - password: d2VsY29tZTEK # welcome1 i.e.'WebLogic password' + password: V2VsY29tZTE= # Welcome1 i.e.'WebLogic password' user: d2VibG9naWM= # weblogic i.e. 'WebLogic username' type: Opaque --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: - name: wls-exporter-wcp-domain + name: wls-exporter namespace: monitoring labels: k8s-app: wls-exporter @@ -40,3 +40,4 @@ spec: interval: 10s honorLabels: true path: /wls-exporter/metrics + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml.template b/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml.template new file mode 100644 index 000000000..63328f19d --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/manifests/wls-exporter-ServiceMonitor.yaml.template @@ -0,0 +1,44 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Secret +metadata: + name: basic-auth + namespace: wcpns +data: + password: %PASSWORD% + user: %USERNAME% +type: Opaque +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: wls-exporter + namespace: wcpns + labels: + k8s-app: wls-exporter + release: monitoring +spec: + namespaceSelector: + matchNames: + - wcpns + selector: + matchLabels: + weblogic.domainName: wcp-domain + endpoints: + - basicAuth: + password: + name: basic-auth + key: password + username: + name: basic-auth + key: user + port: default + relabelings: + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + interval: 10s + honorLabels: true + path: /wls-exporter/metrics + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/monitoring-inputs.yaml b/OracleWebCenterPortal/kubernetes/monitoring-service/monitoring-inputs.yaml new file mode 100644 index 000000000..a2b3c6647 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/monitoring-inputs.yaml @@ -0,0 +1,64 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# The version of this inputs file. Do not modify. +version: create-wcp-domain-monitoring-inputs-v1 + +# Unique ID identifying your domain. +# This ID must not contain an underscope ("_"), and must be lowercase and unique across all domains in a Kubernetes cluster. +domainUID: wcp-domain + +# Name of the domain namespace +domainNamespace: wcpns + +# Boolean value indicating whether to install kube-prometheus-stack +setupKubePrometheusStack: true + +# Additional parameters for helm install kube-prometheus-stack +# Refer https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/values.yaml for additional parameters +# Sample : +# additionalParamForKubePrometheusStack: --set nodeExporter.enabled=false --set prometheusOperator.tls.enabled=false --set prometheusOperator.admissionWebhooks.enabled=false +additionalParamForKubePrometheusStack: + +# Name of the monitoring namespace +monitoringNamespace: monitoring + +# Name of the Admin Server +adminServerName: AdminServer +# +# Port number for admin server +adminServerPort: 7001 + +# Cluster name +wcpClusterName: wcp-cluster + +# Port number for managed server +wcpManagedServerPort: 8888 + +# WebLogic Monitoring Exporter to Cluster +wlsMonitoringExporterTowcpCluster: false + +# Portlet Cluster name +wcpPortletClusterName: wcportlet-cluster + +# Port number for Portlet managed server +wcpPortletManagedServerPort: 8889 + +# WebLogic Monitoring Exporter to PortletCluster +wlsMonitoringExporterTowcpPortletCluster: false + +# Boolean to indicate if the adminNodePort will be exposed +exposeMonitoringNodePort: false + +# NodePort to expose Prometheus +prometheusNodePort: 32101 + +# NodePort to expose Grafana +grafanaNodePort: 32100 + +# NodePort to expose Alertmanager +alertmanagerNodePort: 32102 + +# Name of the Kubernetes secret for the Admin Server's username and password +weblogicCredentialsSecretName: wcp-domain-domain-credentials + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/deploy-weblogic-monitoring-exporter.py b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/deploy-weblogic-monitoring-exporter.py new file mode 100644 index 000000000..ebc5d0932 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/deploy-weblogic-monitoring-exporter.py @@ -0,0 +1,105 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +import sys +#======================================================= +# Function for fresh plain deployment +#======================================================= +def newDeploy(appName,target): + try: + print 'Deploying .........' + deploy(appName,'/u01/oracle/wls-exporter-deploy/'+appName+'.war', target, upload="true",remote="true") + startApplication(appName) + except Exception, ex: + print ex.toString() + +#======================================================== +# Main program here... +# Target you can change as per your need +#======================================================== + +def usage(): + argsList = ' -domainName -adminServerName -adminURL -username -password ' + argsList=argsList + ' -wcpClusterName ' + ' -wlsMonitoringExporterTowcpCluster ' + argsList=argsList + ' -wcpPortletClusterName ' + ' -wlsMonitoringExporterTowcpPortletCluster ' + print sys.argv[0] + argsList + sys.exit(0) + +if len(sys.argv) < 1: + usage() + +# domainName will be passed by command line parameter -domainName. +domainName = "wcp-domain" + +# adminServerName will be passed by command line parameter -adminServerName +adminServerName = "AdminServer" + +# adminURL will be passed by command line parameter -adminURL +adminURL = "wcp-domain-adminserver:7001" + +# wcpClusterName will be passed by command line parameter -wcpClusterName +wcpClusterName = "wcp-cluster" + +# wlsMonitoringExporterTowcpCluster will be passed by command line parameter -wlsMonitoringExporterTowcpCluster +wlsMonitoringExporterTowcpCluster = "false" + + +# wcpPortletClusterName will be passed by command line parameter -wcpPortletClusterName +wcpPortletClusterName = "wcportlet-cluster" + +# wlsMonitoringExporterTowcpPortletCluster will be passed by command line parameter -wlsMonitoringExporterTowcpPortletCluster +wlsMonitoringExporterTowcpPortletCluster = "false" + +# username will be passed by command line parameter -username +username = "weblogic" + +# password will be passed by command line parameter -password +password = "Welcome1" + +i=1 +while i < len(sys.argv): + if sys.argv[i] == '-domainName': + domainName = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-adminServerName': + adminServerName = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-adminURL': + adminURL = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-username': + username = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-password': + password = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-wcpClusterName': + wcpClusterName = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-wlsMonitoringExporterTowcpCluster': + wlsMonitoringExporterTowcpCluster = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-wcpPortletClusterName': + wcpPortletClusterName = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-wlsMonitoringExporterTowcpPortletCluster': + wlsMonitoringExporterTowcpPortletCluster = sys.argv[i+1] + i += 2 + else: + print 'Unexpected argument switch at position ' + str(i) + ': ' + str(sys.argv[i]) + usage() + sys.exit(1) + +# Deployment +connect(username, password, 't3://' + adminURL) +cd('AppDeployments') +newDeploy('wls-exporter-adminserver',adminServerName) +if 'true' == wlsMonitoringExporterTowcpCluster: + newDeploy('wls-exporter-wcp',wcpClusterName) + +if 'true' == wlsMonitoringExporterTowcpPortletCluster: + newDeploy('wls-exporter-wcpPortlet',wcpPortletClusterName) + +disconnect() +exit() + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/deploy-weblogic-monitoring-exporter.sh b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/deploy-weblogic-monitoring-exporter.sh new file mode 100644 index 000000000..32895973a --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/deploy-weblogic-monitoring-exporter.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +warDir=$PWD +source ${scriptDir}/utils.sh + +# Setting default values +initialize +# Function to lowercase a value and make it a legal DNS1123 name +# $1 - value to convert to lowercase +function toDNS1123Legal { + local val=`echo $1 | tr "[:upper:]" "[:lower:]"` + val=${val//"_"/"-"} + echo "$val" +} + +# username and password from Kubernetes secret +username=`kubectl get secrets ${weblogicCredentialsSecretName} -n ${domainNamespace} -o=jsonpath='{.data.username}'|base64 --decode` +password=`kubectl get secrets ${weblogicCredentialsSecretName} -n ${domainNamespace} -o=jsonpath='{.data.password}'|base64 --decode` + +adminServerPodName="${domainUID}-$(toDNS1123Legal ${adminServerName})" + +InputParameterList=" -domainName ${domainUID} -adminServerName ${adminServerName} -adminURL ${adminServerPodName}:${adminServerPort} -username ${username} -password ${password}" +InputParameterList="${InputParameterList} -wcpClusterName ${wcpClusterName} -wlsMonitoringExporterTowcpCluster ${wlsMonitoringExporterTowcpCluster}" +InputParameterList="${InputParameterList} -wcpPortletClusterName ${wcpPortletClusterName} -wlsMonitoringExporterTowcpPortletCluster ${wlsMonitoringExporterTowcpPortletCluster}" + +echo "Deploying WebLogic Monitoring Exporter with domainNamespace[$domainNamespace], domainUID[$domainUID], adminServerPodName[$adminServerPodName]" +. $scriptDir/get-wls-exporter.sh +kubectl cp $scriptDir/wls-exporter-deploy ${domainNamespace}/${adminServerPodName}:/u01/oracle +kubectl cp $scriptDir/deploy-weblogic-monitoring-exporter.py ${domainNamespace}/${adminServerPodName}:/u01/oracle/wls-exporter-deploy +EXEC_DEPLOY="kubectl exec -it -n ${domainNamespace} ${adminServerPodName} -- /u01/oracle/oracle_common/common/bin/wlst.sh /u01/oracle/wls-exporter-deploy/deploy-weblogic-monitoring-exporter.py ${InputParameterList}" +eval ${EXEC_DEPLOY} + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/get-wls-exporter.sh b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/get-wls-exporter.sh new file mode 100644 index 000000000..f4f47a7b7 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/get-wls-exporter.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/utils.sh +warDir=$scriptDir/../bin +mkdir -p $warDir +curl -L -o $warDir/wls-exporter.war https://github.com/oracle/weblogic-monitoring-exporter/releases/download/v2.0.0/wls-exporter.war +mkdir -p $scriptDir/wls-exporter-deploy +echo "created $scriptDir/wls-exporter-deploy dir" + +function update_wls_exporter_war { + servername=$1 + port=$2 + tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX) + echo "created $tmp_dir" + mkdir -p $tmp_dir/WEB-INF + cp $scriptDir/../config/config.yml.template $tmp_dir/config.yml + cp $scriptDir/../config/weblogic.xml $tmp_dir/WEB-INF/weblogic.xml + cp $warDir/wls-exporter.war $tmp_dir/wls-exporter.war + + sed -i -e "s:%PORT%:${port}:g" $tmp_dir/config.yml + pushd $tmp_dir + echo "in temp dir" + zip wls-exporter.war WEB-INF/weblogic.xml + zip wls-exporter.war config.yml + + cp wls-exporter.war ${scriptDir}/wls-exporter-deploy/wls-exporter-${servername}.war + popd +} + +initialize + +update_wls_exporter_war adminserver ${adminServerPort} +if [[ ${wlsMonitoringExporterTowcpCluster} == "true" ]]; +then + update_wls_exporter_war wcp ${wcpManagedServerPort} +fi +if [[ ${wlsMonitoringExporterTowcpPortletCluster} == "true" ]]; +then + update_wls_exporter_war wcpPortlet ${wcpPortletManagedServerPort} +fi + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/undeploy-weblogic-monitoring-exporter.py b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/undeploy-weblogic-monitoring-exporter.py new file mode 100644 index 000000000..52fc3d040 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/undeploy-weblogic-monitoring-exporter.py @@ -0,0 +1,103 @@ +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +import sys +#======================================================= +# Function for undeployment +#======================================================= +def unDeploy(appName,target): + print 'Undeploying .........' + try: + stopApplication(appName) + undeploy(appName, target) + except Exception, ex: + print ex.toString() + +#======================================================== +# Main program here... +# Target you can change as per your need +#======================================================== +def usage(): + argsList = ' -domainName -adminServerName -adminURL -username -password ' + argsList=argsList + ' -wcpClusterName ' + ' -wlsMonitoringExporterTowcpCluster ' + argsList=argsList + ' -wcpPortletClusterName ' + ' -wlsMonitoringExporterTowcpPortletCluster ' + print sys.argv[0] + argsList + sys.exit(0) + +if len(sys.argv) < 1: + usage() + +# domainName will be passed by command line parameter -domainName. +domainName = "wcp-domain" + +# adminServerName will be passed by command line parameter -adminServerName +adminServerName = "AdminServer" + +# adminURL will be passed by command line parameter -adminURL +adminURL = "wcp-domain-adminserver:7001" + +# wcpClusterName will be passed by command line parameter -wcpClusterName +wcpClusterName = "wcp-cluster" + +# wlsMonitoringExporterTowcpCluster will be passed by command line parameter -wlsMonitoringExporterTowcpCluster +wlsMonitoringExporterTowcpCluster = "false" +# wcpPortletClusterName will be passed by command line parameter -wcpPortletClusterName +wcpPortletClusterName = "wcportlet-cluster" + +# wlsMonitoringExporterTowcpPortletCluster will be passed by command line parameter -wlsMonitoringExporterTowcpPortletCluster +wlsMonitoringExporterTowcpPortletCluster = "false" + +# username will be passed by command line parameter -username +username = "weblogic" + +# password will be passed by command line parameter -password +password = "Welcome1" + + +i=1 +while i < len(sys.argv): + if sys.argv[i] == '-domainName': + domainName = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-adminServerName': + adminServerName = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-adminURL': + adminURL = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-username': + username = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-password': + password = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-wcpClusterName': + wcpClusterName = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-wlsMonitoringExporterTowcpCluster': + wlsMonitoringExporterTowcpCluster = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-wcpPortletClusterName': + wcpPortletClusterName = sys.argv[i+1] + i += 2 + elif sys.argv[i] == '-wlsMonitoringExporterTowcpPortletCluster': + wlsMonitoringExporterTowcpPortletCluster = sys.argv[i+1] + i += 2 + + else: + print 'Unexpected argument switch at position ' + str(i) + ': ' + str(sys.argv[i]) + usage() + sys.exit(1) + +# Undeploy +connect(username, password, 't3://' + adminURL) +unDeploy('wls-exporter-adminserver',adminServerName) +if 'true' == wlsMonitoringExporterTowcpCluster: + unDeploy('wls-exporter-wcp',wcpClusterName) + +if 'true' == wlsMonitoringExporterTowcpPortletCluster: + unDeploy('wls-exporter-wcpPortlet',wcpPortletClusterName) + +disconnect() +exit() + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/undeploy-weblogic-monitoring-exporter.sh b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/undeploy-weblogic-monitoring-exporter.sh new file mode 100644 index 000000000..873ea52c2 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/undeploy-weblogic-monitoring-exporter.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +source ${scriptDir}/utils.sh + +# Function to lowercase a value and make it a legal DNS1123 name +# $1 - value to convert to lowercase +function toDNS1123Legal { + local val=`echo $1 | tr "[:upper:]" "[:lower:]"` + val=${val//"_"/"-"} + echo "$val" +} + +initialize + +# username and password from Kubernetes secret +username=`kubectl get secrets ${weblogicCredentialsSecretName} -n ${domainNamespace} -o=jsonpath='{.data.username}'|base64 --decode` +password=`kubectl get secrets ${weblogicCredentialsSecretName} -n ${domainNamespace} -o=jsonpath='{.data.password}'|base64 --decode` + +adminServerPodName="${domainUID}-$(toDNS1123Legal ${adminServerName})" + +InputParameterList="-domainName ${domainUID} -adminServerName ${adminServerName} -adminURL ${adminServerPodName}:${adminServerPort} -username ${username} -password ${password}" +InputParameterList="${InputParameterList} -wcpClusterName ${wcpClusterName} -wlsMonitoringExporterTowcpCluster ${wlsMonitoringExporterTowcpCluster}" +InputParameterList="${InputParameterList} -wcpPortletClusterName ${wcpPortletClusterName} -wlsMonitoringExporterTowcpPortletCluster ${wlsMonitoringExporterTowcpPortletCluster}" + +# Copy weblogic monitoring exporter jars for deployment +echo "Undeploying WebLogic Monitoring Exporter: domainNamespace[$domainNamespace], domainUID[$domainUID], adminServerPodName[$adminServerPodName]" + +kubectl cp $scriptDir/undeploy-weblogic-monitoring-exporter.py ${domainNamespace}/${adminServerPodName}:/u01/oracle/undeploy-weblogic-monitoring-exporter.py +EXEC_UNDEPLOY="kubectl exec -it -n ${domainNamespace} ${adminServerPodName} -- /u01/oracle/oracle_common/common/bin/wlst.sh /u01/oracle/undeploy-weblogic-monitoring-exporter.py ${InputParameterList}" +eval ${EXEC_UNDEPLOY} + +# Cleanup the local wars +rm -rf ${scriptDir}/wls-exporter-deploy + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/utils.sh b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/utils.sh new file mode 100644 index 000000000..7d68513a2 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/scripts/utils.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# + +function initialize { + if [ -z ${domainNamespace} ]; then + echo "domainNamespace is empty, setting to default wcpns" + domainNamespace="wcpns" + fi + + if [ -z ${domainUID} ]; then + echo "domainUID is empty, setting to default wcp-domain" + domainUID="wcp-domain" + fi + + if [ -z ${weblogicCredentialsSecretName} ]; then + echo "weblogicCredentialsSecretName is empty, setting to default \"wcp-domain-domain-credentials\"" + weblogicCredentialsSecretName="wcp-domain-domain-credentials" + fi + + if [ -z ${adminServerName} ]; then + echo "adminServerName is empty, setting to default \"AdminServer\"" + adminServerName="AdminServer" + fi + + if [ -z ${adminServerPort} ]; then + echo "adminServerPort is empty, setting to default \"7001\"" + adminServerPort="7001" + fi + + if [ -z ${wcpClusterName} ]; then + echo "wcpClusterName is empty, setting to default \"wcp-cluster\"" + wcpClusterName="wcp-cluster" + fi + + if [ -z ${wcpManagedServerPort} ]; then + echo "wcpManagedServerPort is empty, setting to default \"8888\"" + wcpManagedServerPort="8888" + fi + + if [ -z ${wlsMonitoringExporterTowcpCluster} ]; then + echo "wlsMonitoringExporterTowcpCluster is empty, setting to default \"false\"" + wlsMonitoringExporterTowcpCluster="false" + fi + if [ -z ${wcpPortletClusterName} ]; then + echo "wcpPortletClusterName is empty, setting to default \"wcportlet-cluster\"" + wcpPortletClusterName="wcportlet-cluster" + fi + + if [ -z ${wcpPortletManagedServerPort} ]; then + echo "wcpPortletManagedServerPort is empty, setting to default \"8889\"" + wcpPortletManagedServerPort="8889" + fi + + if [ -z ${wlsMonitoringExporterTowcpPortletCluster} ]; then + echo "wlsMonitoringExporterTowcpPortletCluster is empty, setting to default \"false\"" + wlsMonitoringExporterTowcpPortletCluster="false" + fi +} + diff --git a/OracleWebCenterPortal/kubernetes/monitoring-service/setup-monitoring.sh b/OracleWebCenterPortal/kubernetes/monitoring-service/setup-monitoring.sh new file mode 100644 index 000000000..bf7d3619c --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/monitoring-service/setup-monitoring.sh @@ -0,0 +1,194 @@ +#!/bin/bash +# Copyright (c) 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# setup-monitoring.sh + +# Initialize +script="${BASH_SOURCE[0]}" +scriptDir="$( cd "$( dirname "${script}" )" && pwd )" +OLD_PWD=`pwd` + + + +# +# Function to exit and print an error message +# $1 - text of message +function fail { + printError $* + exit 1 +} + +# Function to print an error message +function printError { + echo [ERROR] $* +} + + +# +# Function to remove a file if it exists +# +function removeFileIfExists { + echo "input is $1" + if [ -f $1 ]; then + rm -f $1 + fi +} + +function exitIfError { + if [ "$1" != "0" ]; then + echo "$2" + exit $1 + fi +} + +# +# Function to parse a yaml file and generate the bash exports +# $1 - Input filename +# $2 - Output filename +function parseYaml { + local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') + sed -ne "s|^\($s\):|\1|" \ + -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | + awk -F$fs '{ + if (length($3) > 0) { + # javaOptions may contain tokens that are not allowed in export command + # we need to handle it differently. + if ($2=="javaOptions") { + printf("%s=%s\n", $2, $3); + } else { + printf("export %s=\"%s\"\n", $2, $3); + } + } + }' > $2 +} + +function usage { + echo usage: ${script} -i file [-v] [-h] + echo " -i Parameter inputs file, must be specified." + echo " -h Help" + exit $1 +} + +function installKubePrometheusStack { + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm repo update + echo "Setup prometheus-community/kube-prometheus-stack in progress" + if [ ${exposeMonitoringNodePort} == "true" ]; then + + helm install ${monitoringNamespace} prometheus-community/kube-prometheus-stack \ + --namespace ${monitoringNamespace} ${additionalParamForKubePrometheusStack} \ + --set prometheus.service.type=NodePort --set prometheus.service.nodePort=${prometheusNodePort} \ + --set alertmanager.service.type=NodePort --set alertmanager.service.nodePort=${alertmanagerNodePort} \ + --set grafana.adminPassword=admin --set grafana.service.type=NodePort --set grafana.service.nodePort=${grafanaNodePort} \ + --version "16.5.0" \ + --atomic --wait + else + helm install ${monitoringNamespace} prometheus-community/kube-prometheus-stack \ + --namespace ${monitoringNamespace} ${additionalParamForKubePrometheusStack} \ + --set grafana.adminPassword=admin \ + --version "16.5.0" \ + --atomic --wait + fi + exitIfError $? "ERROR: prometheus-community/kube-prometheus-stack install failed." +} + +#Parse the inputs +while getopts "hi:" opt; do + case $opt in + i) valuesInputFile="${OPTARG}" + ;; + h) usage 0 + ;; + *) usage 1 + ;; + esac +done + +if [ -z ${valuesInputFile} ]; then + echo "${script}: -i must be specified." + missingRequiredOption="true" +fi + +if [ "${missingRequiredOption}" == "true" ]; then + usage 1 +fi + +if [ ! -f ${valuesInputFile} ]; then + echo "Unable to locate the input parameters file ${valuesInputFile}" + fail 'The error listed above must be resolved before the script can continue' +fi + + +exportValuesFile=$(mktemp /tmp/export-values-XXXXXXXXX.sh) +parseYaml ${valuesInputFile} ${exportValuesFile} + + +source ${exportValuesFile} +rm ${exportValuesFile} + + +if [ "${setupKubePrometheusStack}" = "true" ]; then + if test "$(kubectl get namespace ${monitoringNamespace} --ignore-not-found | wc -l)" = 0; then + echo "The namespace ${monitoringNamespace} for install prometheus-community/kube-promethues-stack does not exist. Creating the namespace ${monitoringNamespace}" + kubectl create namespace ${monitoringNamespace} + fi + echo -e "Monitoring setup in ${monitoringNamespace} in progress.......\n" + + # Create the namespace and CRDs, and then wait for them to be availble before creating the remaining resources + kubectl label nodes --all kubernetes.io/os=linux --overwrite=true + + echo "Setup prometheus-community/kube-prometheus-stack started" + installKubePrometheusStack + cd $OLD_PWD + + echo "Setup prometheus-community/kube-prometheus-stack completed" +fi + +export username=`kubectl get secrets ${weblogicCredentialsSecretName} -n ${domainNamespace} -o=jsonpath='{.data.username}'|base64 --decode` +export password=`kubectl get secrets ${weblogicCredentialsSecretName} -n ${domainNamespace} -o=jsonpath='{.data.password}'|base64 --decode` + +# Setting up the WebLogic Monitoring Exporter +echo "Deploy WebLogic Monitoring Exporter started" +script=${scriptDir}/scripts/deploy-weblogic-monitoring-exporter.sh +sh ${script} +exitIfError $? "ERROR: $script failed." +echo "Deploy WebLogic Monitoring Exporter completed" + + +# Deploy servicemonitors +serviceMonitor=${scriptDir}/manifests/wls-exporter-ServiceMonitor.yaml +cp "${serviceMonitor}.template" "${serviceMonitor}" +sed -i -e "s/release: monitoring/release: ${monitoringNamespace}/g" ${serviceMonitor} +sed -i -e "s/user: %USERNAME%/user: `echo -n $username|base64 -w0`/g" ${serviceMonitor} +sed -i -e "s/password: %PASSWORD%/password: `echo -n $password|base64 -w0`/g" ${serviceMonitor} +sed -i -e "s/namespace:.*/namespace: ${domainNamespace}/g" ${serviceMonitor} +sed -i -e "s/weblogic.domainName:.*/weblogic.domainName: ${domainUID}/g" ${serviceMonitor} +sed -i -e "$!N;s/matchNames:\n -.*/matchNames:\n - ${domainNamespace}/g;P;D" ${serviceMonitor} + +kubectl apply -f ${serviceMonitor} + + +if [ "${setupKubePrometheusStack}" = "true" ]; then + # Deploying WebLogic Server Grafana Dashboard + echo "Deploying WebLogic Server Grafana Dashboard...." + grafanaEndpointIP=$(kubectl get endpoints ${monitoringNamespace}-grafana -n ${monitoringNamespace} -o=jsonpath="{.subsets[].addresses[].ip}") + grafanaEndpointPort=$(kubectl get endpoints ${monitoringNamespace}-grafana -n ${monitoringNamespace} -o=jsonpath="{.subsets[].ports[].port}") + grafanaEndpoint="${grafanaEndpointIP}:${grafanaEndpointPort}" + curl --noproxy "*" -X POST -H "Content-Type: application/json" -d @config/weblogic-server-dashboard.json http://admin:admin@${grafanaEndpoint}/api/dashboards/db + echo "" + echo "Deployed WebLogic Server Grafana Dashboard successfully" + echo "" + if [ ${exposeMonitoringNodePort} == "true" ]; then + echo "Grafana is available at NodePort: ${grafanaNodePort}" + echo "Prometheus is available at NodePort: ${prometheusNodePort}" + echo "Altermanager is available at NodePort: ${alertmanagerNodePort}" + echo "==============================================================" + fi +else + echo "Please import config/weblogic-server-dashboard.json manually into Grafana" +fi + +echo "" + diff --git a/OracleWebCenterPortal/kubernetes/rest/README.md b/OracleWebCenterPortal/kubernetes/rest/README.md new file mode 100644 index 000000000..f0e09b088 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/rest/README.md @@ -0,0 +1,38 @@ +# Sample to create certificates and keys for the operator + +When a user enables the operator's external REST API (by setting +`externalRestEnabled` to `true` when installing the operator Helm chart), the user needs +to provide the certificate and private key for api's SSL identity too (by creating a +`tls secret` before the installation of the operator helm chart). + +This sample script generates a self-signed certificate and private key that can be used +for the operator's external REST api when experimenting with the operator. They should +not be used in a production environment. + +The syntax of the script is: +```shell +$ kubernetes/samples/scripts/rest/generate-external-rest-identity.sh -n [-s ] +``` + +Where `` lists the subject alternative names to put into the generated self-signed +certificate for the external WebLogic Operator REST HTTPS interface, should match +the namespace where the operator will be installed, and optionally the secret name, which defaults +to `weblogic-operator-external-rest-identity`. Each must be prefaced +by `DNS:` (for a name) or `IP:` (for an address), for example: +``` +DNS:myhost,DNS:localhost,IP:127.0.0.1 +``` + +You should include the addresses of all masters and load balancers in this list. The certificate +cannot be conveniently changed after installation of the operator. + +The script creates the secret in the weblogic-operator namespace with the self-signed +certificate and private key + +Example usage: +```shell +$ generate-external-rest-identity.sh IP:127.0.0.1 -n weblogic-operator > my_values.yaml +$ echo "externalRestEnabled: true" >> my_values.yaml + ... +$ helm install my_operator kubernetes/charts/weblogic-operator --namespace my_operator-ns --values my_values.yaml --wait +``` diff --git a/OracleWebCenterPortal/kubernetes/rest/generate-external-rest-identity.sh b/OracleWebCenterPortal/kubernetes/rest/generate-external-rest-identity.sh new file mode 100644 index 000000000..e645d3925 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/rest/generate-external-rest-identity.sh @@ -0,0 +1,200 @@ +#!/usr/bin/env bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +# When the customer enables the operator's external REST api (by setting +# externalRestEnabled to true when installing the operator helm chart), the customer needs +# to provide the certificate and private key for api's SSL identity too (by creating a +# tls secret before the installation of the operator helm chart). +# +# This sample script generates a self-signed certificate and private key that can be used +# for the operator's external REST api when experimenting with the operator. They should +# not be used in a production environment. +# +# The sytax of the script is: +# +# kubernetes/samples/scripts/rest/generate-external-rest-identity.sh -a -n +# +# Where lists the subject alternative names to put into the generated self-signed +# certificate for the external WebLogic Operator REST https interface, for example: +# +# DNS:myhost,DNS:localhost,IP:127.0.0.1 +# +# You should include the addresses of all masters and load balancers in this list. The certificate +# cannot be conveniently changed after installation of the operator. +# +# The script creates the secret in the weblogic-operator namespace with the self-signed +# certificate and private key +# +# Example usage: +# generate-external-rest-identity.sh -a IP:127.0.0.1 -n weblogic-operator > my_values.yaml +# echo "externalRestEnabled: true" >> my_values.yaml +# ... +# helm install my_operator kubernetes/charts/weblogic-operator --namespace my_operator-ns --values my_values.yaml --wait +usage(){ +cat < -n +Options: +-a SANS Required, the SANs for the certificate +-n NAMESPACE Required, the namespace where the secret will be created. +-s SECRET_NAME Optional, the name of the kubernetes secret. Default is: weblogic-operator-external-rest-identity. +-h, --help Display this help text. +EOF +exit 1 +} + +if [ ! -x "$(command -v keytool)" ]; then + echo "Can't find keytool. Please add it to the path." + exit 1 +fi + +if [ ! -x "$(command -v openssl)" ]; then + echo "Can't find openssl. Please add it to the path." + exit 1 +fi + +if [ ! -x "$(command -v base64)" ]; then + echo "Can't find base64. Please add it to the path." + exit 1 +fi + +TEMP_DIR=`mktemp -d` +if [ $? -ne 0 ]; then + echo "$0: Can't create temp directory." + exit 1 +fi + +if [ -z $TEMP_DIR ]; then + echo "Can't create temp directory." + exit 1 +fi + +function cleanup { + rm -r $TEMP_DIR + if [[ $SUCCEEDED != "true" ]]; then + exit 1 + fi +} + +set -e +#set -x + +trap "cleanup" EXIT + +SECRET_NAME="weblogic-operator-external-rest-identity" + +while [ $# -gt 0 ] + do + key="$1" + case $key in + -a) + shift # past argument + if [ $# -eq 0 ] || [ ${1:0:1} == "-" ]; then echo "SANs is required and is missing"; usage; fi + SANS=$1 + shift # past value + ;; + -n) + shift # past argument + if [ $# -eq 0 ] || [ ${1:0:1} == "-" ]; then echo "Namespace is required and is missing"; usage; fi + NAMESPACE=$1 + shift # past value + ;; + -s) + shift # past argument + if [ $# -eq 0 ] || [ ${1:0:1} == "-" ]; then echo "Invalid secret name $1"; usage; fi + SECRET_NAME=$1 + shift # past value + ;; + -h) + shift # past argument + ;; + *) + SANS=$1 + shift # past argument + ;; + esac +done + +if [ -z "$SANS" ] +then + 1>&2 + echo "SANs is required and is missing" + usage +fi + +if [ -z "$NAMESPACE" ] +then + 1>&2 + echo "Namespace is required and is missing" + usage +fi + +DAYS_VALID="3650" +TEMP_PW="temp_password" +OP_PREFIX="weblogic-operator" +OP_ALIAS="${OP_PREFIX}-alias" +OP_JKS="${TEMP_DIR}/${OP_PREFIX}.jks" +OP_PKCS12="${TEMP_DIR}/${OP_PREFIX}.p12" +OP_CSR="${TEMP_DIR}/${OP_PREFIX}.csr" +OP_CERT_PEM="${TEMP_DIR}/${OP_PREFIX}.cert.pem" +OP_KEY_PEM="${TEMP_DIR}/${OP_PREFIX}.key.pem" + +# generate a keypair for the operator's REST service, putting it in a keystore +keytool \ + -genkey \ + -keystore ${OP_JKS} \ + -alias ${OP_ALIAS} \ + -storepass ${TEMP_PW} \ + -keypass ${TEMP_PW} \ + -keysize 2048 \ + -keyalg RSA \ + -validity ${DAYS_VALID} \ + -dname "CN=weblogic-operator" \ + -ext KU=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement \ + -ext SAN="${SANS}" \ +2> /dev/null + +# extract the cert to a pem file +keytool \ + -exportcert \ + -keystore ${OP_JKS} \ + -storepass ${TEMP_PW} \ + -alias ${OP_ALIAS} \ + -rfc \ +> ${OP_CERT_PEM} 2> /dev/null + +# convert the keystore to a pkcs12 file +keytool \ + -importkeystore \ + -srckeystore ${OP_JKS} \ + -srcstorepass ${TEMP_PW} \ + -destkeystore ${OP_PKCS12} \ + -srcstorepass ${TEMP_PW} \ + -deststorepass ${TEMP_PW} \ + -deststoretype PKCS12 \ +2> /dev/null + +# extract the private key from the pkcs12 file to a pem file +openssl \ + pkcs12 \ + -in ${OP_PKCS12} \ + -passin pass:${TEMP_PW} \ + -nodes \ + -nocerts \ + -out ${OP_KEY_PEM} \ +2> /dev/null + +set +e +# Check if namespace exist +kubectl get namespace $NAMESPACE >/dev/null 2>/dev/null +if [ $? -eq 1 ]; then + echo "Namespace $NAMESPACE does not exist" + exit 1 +fi +kubectl get secret $SECRET_NAME -n $NAMESPACE >/dev/null 2>/dev/null +if [ $? -eq 1 ]; then + kubectl create secret tls "$SECRET_NAME" --cert=${OP_CERT_PEM} --key=${OP_KEY_PEM} -n $NAMESPACE >/dev/null +fi +echo "externalRestIdentitySecret: $SECRET_NAME" + +SUCCEEDED=true diff --git a/OracleWebCenterPortal/kubernetes/scaling/scalingAction.sh b/OracleWebCenterPortal/kubernetes/scaling/scalingAction.sh new file mode 100644 index 000000000..0da098e68 --- /dev/null +++ b/OracleWebCenterPortal/kubernetes/scaling/scalingAction.sh @@ -0,0 +1,504 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +# script parameters +scaling_action="" +wls_domain_uid="" +wls_cluster_name="" +wls_domain_namespace="default" +operator_service_name="internal-weblogic-operator-svc" +operator_namespace="weblogic-operator" +operator_service_account="weblogic-operator" +scaling_size=1 +access_token="" +no_op="" +kubernetes_master="https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}" +log_file_name="scalingAction.log" + +# timestamp +# purpose: echo timestamp in the form yyyy-mm-ddThh:mm:ss.nnnnnnZ +# example: 2018-10-01T14:00:00.000001Z +function timestamp() { + local timestamp="`date --utc '+%Y-%m-%dT%H:%M:%S.%NZ' 2>&1`" + if [ ! "${timestamp/illegal/xyz}" = "${timestamp}" ]; then + # old shell versions don't support %N or --utc + timestamp="`date -u '+%Y-%m-%dT%H:%M:%S.000000Z' 2>&1`" + fi + echo "${timestamp}" +} + +function trace() { + echo "@[$(timestamp)][$wls_domain_namespace][$wls_domain_uid][$wls_cluster_name][INFO]" "$@" >> ${log_file_name} +} + +function print_usage() { + echo "Usage: scalingAction.sh --action=[scaleUp | scaleDown] --domain_uid= --cluster_name= [--kubernetes_master=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}] [--access_token=] [--wls_domain_namespace=default] [--operator_namespace=weblogic-operator] [--operator_service_name=weblogic-operator] [--scaling_size=1] [--no_op]" + echo " where" + echo " action - scaleUp or scaleDown" + echo " domain_uid - WebLogic Domain Unique Identifier" + echo " cluster_name - WebLogic Cluster Name" + echo " kubernetes_master - Kubernetes master URL, default=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}" + echo " access_token - Service Account Bearer token for authentication and authorization for access to REST Resources" + echo " wls_domain_namespace - Kubernetes name space WebLogic Domain is defined in, default=default" + echo " operator_service_name - WebLogic Operator Service name, default=internal-weblogic-operator-svc" + echo " operator_service_account - Kubernetes Service Account for WebLogic Operator, default=weblogic-operator" + echo " operator_namespace - WebLogic Operator Namespace, default=weblogic-operator" + echo " scaling_size - number of WebLogic server instances by which to scale up or down, default=1" + echo " no_op - if specified, returns without doing anything. For use by unit test to include methods in the script" + exit 1 +} + +# Retrieve WebLogic Operator Service Account Token for Authorization +function initialize_access_token() { + if [ -z "$access_token" ] + then + access_token=`cat /var/run/secrets/kubernetes.io/serviceaccount/token` + fi +} + +function logScalingParameters() { + trace "scaling_action: $scaling_action" + trace "wls_domain_uid: $wls_domain_uid" + trace "wls_cluster_name: $wls_cluster_name" + trace "wls_domain_namespace: $wls_domain_namespace" + trace "operator_service_name: $operator_service_name" + trace "operator_service_account: $operator_service_account" + trace "operator_namespace: $operator_namespace" + trace "scaling_size: $scaling_size" +} + +function jq_available() { + if [ -x "$(command -v jq)" ] && [ -z "$DONT_USE_JQ" ]; then + return; + fi + false +} + +# Query WebLogic Operator Service Port +function get_operator_internal_rest_port() { + local STATUS=$(curl \ + -v \ + --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \ + -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ + -X GET $kubernetes_master/api/v1/namespaces/$operator_namespace/services/$operator_service_name/status) + if [ $? -ne 0 ] + then + trace "Failed to retrieve status of $operator_service_name in name space: $operator_namespace" + trace "STATUS: $STATUS" + exit 1 + fi + + local port + if jq_available; then + local extractPortCmd="(.spec.ports[] | select (.name == \"rest\") | .port)" + port=$(echo "${STATUS}" | jq "${extractPortCmd}" 2>> ${log_file_name}) + else +cat > cmds-$$.py << INPUT +import sys, json +for i in json.load(sys.stdin)["spec"]["ports"]: + if i["name"] == "rest": + print(i["port"]) +INPUT +port=$(echo "${STATUS}" | python cmds-$$.py 2>> ${log_file_name}) + fi + echo "$port" +} + +# Retrieve the api version of the deployed Custom Resource Domain +function get_domain_api_version() { + # Retrieve Custom Resource Definition for WebLogic domain + local APIS=$(curl \ + -v \ + --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \ + -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ + -X GET \ + $kubernetes_master/apis) + if [ $? -ne 0 ] + then + trace "Failed to retrieve list of APIs from Kubernetes cluster" + trace "APIS: $APIS" + exit 1 + fi + +# Find domain version + local domain_api_version + if jq_available; then + local extractVersionCmd="(.groups[] | select (.name == \"weblogic.oracle\") | .preferredVersion.version)" + domain_api_version=$(echo "${APIS}" | jq -r "${extractVersionCmd}" 2>> ${log_file_name}) + else +cat > cmds-$$.py << INPUT +import sys, json +for i in json.load(sys.stdin)["groups"]: + if i["name"] == "weblogic.oracle": + print(i["preferredVersion"]["version"]) +INPUT +domain_api_version=`echo ${APIS} | python cmds-$$.py 2>> ${log_file_name}` + fi + echo "$domain_api_version" +} + +# Retrieve Custom Resource Domain +function get_custom_resource_domain() { + local DOMAIN=$(curl \ + -v \ + --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \ + -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ + $kubernetes_master/apis/weblogic.oracle/$domain_api_version/namespaces/$wls_domain_namespace/domains/$wls_domain_uid) + if [ $? -ne 0 ]; then + trace "Failed to retrieve WebLogic Domain Custom Resource Definition" + exit 1 + fi + echo "$DOMAIN" +} + +# Verify if cluster is defined in clusters of the Custom Resource Domain +# args: +# $1 Custom Resource Domain +function is_defined_in_clusters() { + local DOMAIN="$1" + local in_cluster_startup="False" + + if jq_available; then + local inClusterStartupCmd="(.spec.clusters[] | select (.clusterName == \"${wls_cluster_name}\"))" + local clusterDefinedInCRD=$(echo "${DOMAIN}" | jq "${inClusterStartupCmd}" 2>> ${log_file_name}) + if [ "${clusterDefinedInCRD}" != "" ]; then + in_cluster_startup="True" + fi + else +cat > cmds-$$.py << INPUT +import sys, json +outer_loop_must_break = False +for j in json.load(sys.stdin)["spec"]["clusters"]: + if j["clusterName"] == "$wls_cluster_name": + outer_loop_must_break = True + print (True) + break +if outer_loop_must_break == False: + print (False) +INPUT +in_cluster_startup=`echo ${DOMAIN} | python cmds-$$.py 2>> ${log_file_name}` + fi + echo "$in_cluster_startup" +} + +# Gets the current replica count of the cluster +# args: +# $1 Custom Resource Domain +function get_num_ms_in_cluster() { + local DOMAIN="$1" + local num_ms + if jq_available; then + local numManagedServersCmd="(.spec.clusters[] | select (.clusterName == \"${wls_cluster_name}\") | .replicas)" + num_ms=$(echo "${DOMAIN}" | jq "${numManagedServersCmd}" 2>> ${log_file_name}) + else +cat > cmds-$$.py << INPUT +import sys, json +for j in json.load(sys.stdin)["spec"]["clusters"]: + if j["clusterName"] == "$wls_cluster_name": + print (j["replicas"]) +INPUT + num_ms=`echo ${DOMAIN} | python cmds-$$.py 2>> ${log_file_name}` + fi + + if [ "${num_ms}" == "null" ] || [ "${num_ms}" == '' ] ; then + num_ms=0 + fi + + echo "$num_ms" +} + +# Gets the replica count at the Domain level +# args: +# $1 Custom Resource Domain +function get_num_ms_domain_scope() { + local DOMAIN="$1" + local num_ms + if jq_available; then + num_ms=$(echo "${DOMAIN}" | jq -r '.spec.replicas' 2>> ${log_file_name}) + else +cat > cmds-$$.py << INPUT +import sys, json +print (json.load(sys.stdin)["spec"]["replicas"]) +INPUT + num_ms=`echo ${DOMAIN} | python cmds-$$.py 2>> ${log_file_name}` + fi + + if [ "${num_ms}" == "null" ] || [ "${num_ms}" == '' ] ; then + # if not defined then default to 0 + num_ms=0 + fi + + echo "$num_ms" +} + +# +# Function to get minimum replica count for cluster +# $1 - Domain resource in json format +# $2 - Name of the cluster +# $3 - Return value containing minimum replica count +# +function get_min_replicas { + local domainJson=$1 + local clusterName=$2 + local __result=$3 + + eval $__result=0 + if jq_available; then + minReplicaCmd="(.status.clusters[] | select (.clusterName == \"${clusterName}\")) \ + | .minimumReplicas" + minReplicas=$(echo ${domainJson} | jq "${minReplicaCmd}" 2>> ${log_file_name}) + else +cat > cmds-$$.py << INPUT +import sys, json +for j in json.load(sys.stdin)["status"]["clusters"]: + if j["clusterName"] == "$clusterName": + print (j["minimumReplicas"]) +INPUT + minReplicas=`echo ${DOMAIN} | python cmds-$$.py 2>> ${log_file_name}` + fi + eval $__result=${minReplicas} +} + +# Get the current replica count for the WLS cluster if defined in the CRD's Cluster +# configuration. If WLS cluster is not defined in the CRD then return the Domain +# scoped replica value, if present. Returns replica count = 0 if no replica count found. +# args: +# $1 "True" if WLS cluster configuration defined in CRD, "False" otherwise +# $2 Custom Resource Domain +function get_replica_count() { + local in_cluster_startup="$1" + local DOMAIN="$2" + local num_ms + if [ "$in_cluster_startup" == "True" ] + then + trace "$wls_cluster_name defined in clusters" + num_ms=$(get_num_ms_in_cluster "$DOMAIN") + else + trace "$wls_cluster_name NOT defined in clusters" + num_ms=$(get_num_ms_domain_scope "$DOMAIN") + fi + + get_min_replicas "${DOMAIN}" "${wls_cluster_name}" minReplicas + if [[ "${num_ms}" -lt "${minReplicas}" ]]; then + # Reset managed server count to minimum replicas + num_ms=${minReplicas} + fi + + echo "$num_ms" +} + +# Determine the nuber of managed servers to scale +# args: +# $1 scaling action (scaleUp or scaleDown) +# $2 current replica count +# $3 scaling increment value +function calculate_new_ms_count() { + local scaling_action="$1" + local current_replica_count="$2" + local scaling_size="$3" + local new_ms + if [ "$scaling_action" == "scaleUp" ]; + then + # Scale up by specified scaling size + # shellcheck disable=SC2004 + new_ms=$(($current_replica_count + $scaling_size)) + else + # Scale down by specified scaling size + new_ms=$(($current_replica_count - $scaling_size)) + fi + echo "$new_ms" +} + +# Verify if requested managed server scaling count is less than the configured +# minimum replica count for the cluster. +# args: +# $1 Managed server count +# $2 Custom Resource Domain +# $3 Cluster name +function verify_minimum_ms_count_for_cluster() { + local new_ms="$1" + local domainJson="$2" + local clusterName="$3" + # check if replica count is less than minimum replicas + get_min_replicas "${domainJson}" "${clusterName}" minReplicas + if [ "${new_ms}" -lt "${minReplicas}" ]; then + trace "Scaling request to new managed server count $new_ms is less than configured minimum \ + replica count $minReplicas" + exit 1 + fi +} + +# Create the REST endpoint CA certificate in PEM format +# args: +# $1 certificate file name to create +function create_ssl_certificate_file() { + local pem_filename="$1" + if [ ${INTERNAL_OPERATOR_CERT} ]; + then + echo ${INTERNAL_OPERATOR_CERT} | base64 --decode > $pem_filename + else + trace "Operator Cert File not found" + exit 1 + fi +} + +# Create request body for scaling request +# args: +# $1 replica count +function get_request_body() { +local new_ms="$1" +local request_body=$(cat <Note that this release is only for evaluation purposes and hence applicable to Development and Test deployments only. #### Recent changes and known issues @@ -43,3 +46,9 @@ please use this table of contents: * Configuring Kubernetes load balancers * Configuring Prometheus and Grafana to monitor WebCenter Portal * Configuring Logging using ElasticSearch + +#### Documentation for earlier releases + +To view documentation for an earlier release, see: + +* [Version 21.2.3](https://oracle.github.io/fmw-kubernetes/21.2.3/wcportal-domains/) diff --git a/docs-source/content/wcportal-domains/appendix/quickstart-deployment-on-prem.md b/docs-source/content/wcportal-domains/appendix/quickstart-deployment-on-prem.md index 287a74f3a..21c3e2660 100644 --- a/docs-source/content/wcportal-domains/appendix/quickstart-deployment-on-prem.md +++ b/docs-source/content/wcportal-domains/appendix/quickstart-deployment-on-prem.md @@ -125,7 +125,7 @@ Any time you see `YOUR_USERID` in a command, you should replace it with your act 1. Install the latest `docker-engine` and start the Docker service: ``` $ yum-config-manager --enable ol7_addons - $ docker_version="19.03.1.ol" + $ docker_version="19.03.11-ol" $ yum install docker-engine-$docker_version $ systemctl enable docker @@ -144,33 +144,33 @@ Any time you see `YOUR_USERID` in a command, you should replace it with your act Example output: ``` Client: Docker Engine - Community - Version: 19.03.1-ol + Version: 19.03.11-ol API version: 1.40 - Go version: go1.12.5 - Git commit: ead9442 - Built: Wed Sep 11 06:40:28 2019 + Go version: go1.15.5 + Git commit: 748876d + Built: Thu Dec 3 19:36:03 2020 OS/Arch: linux/amd64 Experimental: false - + Server: Docker Engine - Community Engine: - Version: 19.03.1-ol - API version: 1.40 (minimum version 1.12) - Go version: go1.12.5 - Git commit: ead9442 - Built: Wed Sep 11 06:38:43 2019 - OS/Arch: linux/amd64 - Experimental: false - Default Registry: docker.io - containerd: - Version: v1.2.0-rc.0-108-gc444666 - GitCommit: c4446665cb9c30056f4998ed953e6d4ff22c7c39 - runc: - Version: 1.0.0-rc5+dev - GitCommit: 4bb1fe4ace1a32d3676bb98f5d3b6a4e32bf6c58 - docker-init: - Version: 0.18.0 - GitCommit: fec3683 + Version: 19.03.11-ol + API version: 1.40 (minimum version 1.12) + Go version: go1.15.8 + Git commit: f0aae77 + Built: Wed Feb 10 16:13:32 2021 + OS/Arch: linux/amd64 + Experimental: false + Default Registry: docker.io + containerd: + Version: v1.3.9 + GitCommit: + runc: + Version: 1.0.0-rc5+dev + GitCommit: 4bb1fe4ace1a32d3676bb98f5d3b6a4e32bf6c58 + docker-init: + Version: 0.18.0 + GitCommit: fec3683 ``` 1. Update the Docker engine configuration: @@ -275,8 +275,8 @@ Any time you see `YOUR_USERID` in a command, you should replace it with your act $ export HTTPS_PROXY=http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT $ export HTTP_PROXY=http://REPLACE-WITH-YOUR-COMPANY-PROXY-HOST:PORT - ### install kubernetes 1.18.4-1 - $ VERSION=1.18.4-1 + ### install kubernetes 1.20.10 + $ VERSION=1.20.10 $ yum install -y kubelet-$VERSION kubeadm-$VERSION kubectl-$VERSION --disableexcludes=kubernetes ### enable kubelet service so that it auto-restart on reboot @@ -303,17 +303,17 @@ Any time you see `YOUR_USERID` in a command, you should replace it with your act #### 1.4 Set up Helm -1. Install Helm v3.x. +1. Install Helm v3.4+ a. Download Helm from https://github.com/helm/helm/releases. - For example, to download Helm v3.1.3: + For example, to download Helm v3.4.1: ``` - $ wget https://get.helm.sh/helm-v3.1.3-linux-amd64.tar.gz + $ wget https://get.helm.sh/helm-v3.4.1-linux-amd64.tar.gz ``` b. Unpack `tar.gz`: ``` - $ tar -zxvf helm-v3.1.3-linux-amd64.tar.gz + $ tar -zxvf helm-v3.4.1-linux-amd64.tar.gz ``` c. Find the Helm binary in the unpacked directory, and move it to its desired destination: ``` @@ -323,7 +323,7 @@ Any time you see `YOUR_USERID` in a command, you should replace it with your act 1. Run `helm version` to verify its installation: ``` $ helm version - version.BuildInfo{Version:"v3.1.3", GitCommit:"0ad800ef43d3b826f31a5ad8dfbb4fe05d143688", GitTreeState:"clean", GoVersion:"go1.13.12"} + version.BuildInfo{Version:"v3.4.1", GitCommit:"0ad800ef43d3b826f31a5ad8dfbb4fe05d143688", GitTreeState:"clean", GoVersion:"go1.13.12"} ``` ### 2. Set up a single instance Kubernetes cluster @@ -443,7 +443,7 @@ Follow [these steps]({{< relref "/wcportal-domains/installguide/prepare-your-env 1. Pull the operator image: ``` - $ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.1.1 + $ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.3.0 ``` 1. Obtain the Oracle Database image from the [Oracle Container Registry](https://container-registry.oracle.com): @@ -484,10 +484,10 @@ Follow [these steps]({{< relref "/wcportal-domains/installguide/prepare-your-env Use Helm to install and start the operator from the directory you just cloned: ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator - $ helm install weblogic-kubernetes-operator kubernetes/charts/weblogic-operator \ + $ cd ${WORKDIR} + $ helm install weblogic-kubernetes-operator charts/weblogic-operator \ --namespace operator-ns \ - --set image=oracle/weblogic-kubernetes-operator:3.1.1 \ + --set image=oracle/weblogic-kubernetes-operator:3.3.0 \ --set serviceAccount=operator-sa \ --set "domainNamespaces={}" \ --wait @@ -504,11 +504,11 @@ Use Helm to install and start the operator from the directory you just cloned: $ kubectl logs -n operator-ns -c weblogic-operator deployments/weblogic-operator ``` -The WebLogic Kubernetes operator v3.1.1 has been installed. Continue with the load balancer and Oracle WebCenter Portal domain setup. +The WebLogic Kubernetes operator v3.3.0 has been installed. Continue with the load balancer and Oracle WebCenter Portal domain setup. ### 5. Install the Traefik (ingress-based) load balancer -The WebLogic Kubernetes Operator supports three load balancers: Traefik, Voyager, and Apache. Samples are provided in the documentation. +The WebLogic Kubernetes Operator supports three load balancers: Traefik, NGINX and Apache. Samples are provided in the documentation. This Quick Start demonstrates how to install the Traefik ingress controller to provide load balancing for an Oracle WebCenter Portal domain. @@ -524,10 +524,10 @@ This Quick Start demonstrates how to install the Traefik ingress controller to p 1. Install the Traefik operator in the `traefik` namespace with the provided sample values: ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ cd ${WORKDIR} $ helm install traefik traefik/traefik \ --namespace traefik \ - --values kubernetes/samples/scripts/charts/traefik/values.yaml \ + --values charts/traefik/values.yaml \ --set "kubernetes.namespaces={traefik}" \ --set "service.type=NodePort" \ --wait @@ -543,8 +543,8 @@ This Quick Start demonstrates how to install the Traefik ingress controller to p 1. Use Helm to configure the operator to manage Oracle WebCenter Portal domain in this namespace: ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator - $ helm upgrade weblogic-kubernetes-operator kubernetes/charts/weblogic-operator \ + $ cd ${WORKDIR} + $ helm upgrade weblogic-kubernetes-operator charts/weblogic-operator \ --reuse-values \ --namespace operator-ns \ --set "domainNamespaces={wcpns}" \ @@ -556,8 +556,8 @@ This Quick Start demonstrates how to install the Traefik ingress controller to p a. Create a Kubernetes secret for the domain in the same Kubernetes namespace as the domain. In this example, the username is `weblogic`, the password is `welcome1`, and the namespace is `wcpns`: ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-weblogic-domain-credentials - $ sh create-weblogic-credentials.sh -u weblogic -p welcome1 -n wcpns -d wcp-domain -s wcpinfra-domain-credentials + $ cd ${WORKDIR}/create-weblogic-domain-credentials + $ sh create-weblogic-credentials.sh -u weblogic -p welcome1 -n wcpns -d wcp-domain -s wcp-domain-domain-credentials ``` b. Create a Kubernetes secret for the RCU in the same Kubernetes namespace as the domain: @@ -567,11 +567,11 @@ This Quick Start demonstrates how to install the Traefik ingress controller to p * DB sys user password : `Oradoc_db1` * Domain name : `wcp-domain` * Domain Namespace : `wcpns` - * Secret name : `wcpinfra-rcu-credentials` + * Secret name : `wcp-domain-rcu-credentials` ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-rcu-credentials - $ sh create-rcu-credentials.sh -u WCP1 -p Oradoc_db1 -a sys -q Oradoc_db1 -n wcpns -d wcp-domain -s wcpinfra-rcu-credentials + $ cd ${WORKDIR}/create-rcu-credentials + $ sh create-rcu-credentials.sh -u WCP1 -p Oradoc_db1 -a sys -q Oradoc_db1 -n wcpns -d wcp-domain -s wcp-domain-rcu-credentials ``` 1. Create the Kubernetes persistence volume and persistence volume claim. @@ -601,7 +601,7 @@ This Quick Start demonstrates how to install the Traefik ingress controller to p * weblogicDomainStoragePath: `/scratch/k8s_dir` ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-weblogic-domain-pv-pvc + $ cd ${WORKDIR}/create-weblogic-domain-pv-pvc $ cp create-pv-pvc-inputs.yaml create-pv-pvc-inputs.yaml.orig $ sed -i -e "s:baseName\: weblogic-sample:baseName\: domain:g" create-pv-pvc-inputs.yaml $ sed -i -e "s:domainUID\::domainUID\: wcp-domain:g" create-pv-pvc-inputs.yaml @@ -631,7 +631,7 @@ This Quick Start demonstrates how to install the Traefik ingress controller to p a. Create a database in a container: ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-oracle-db-service + $ cd ${WORKDIR}/create-oracle-db-service $ ./start-db-service.sh -i container-registry.oracle.com/database/enterprise:12.2.0.1-slim -p none ``` @@ -641,20 +641,14 @@ This Quick Start demonstrates how to install the Traefik ingress controller to p To create the Oracle WebCenter Portal schemas, run the following commands: ``` - $ kubectl run rcu --generator=run-pod/v1 --image oracle/wcportal:12.2.1.4 -n wcpns -- sleep infinity - #check the status of rcu pod - $ kubectl get pods -n wcpns - #make sure rcu pod status is running before executing this - $ kubectl exec -n wcpns -ti rcu /bin/bash - #After Getting Shell in RCU Container run the below command. - export CONNECTION_STRING=oracle-db.default.svc.cluster.local:1521/devpdb.k8s - export RCUPREFIX=WCP1 - echo -e Oradoc_db1"\n"Oradoc_db1 > /tmp/pwd.txt - /u01/oracle/oracle_common/bin/rcu -silent -dropRepository -databaseType ORACLE -connectString $CONNECTION_STRING -dbUser sys -dbRole sysdba -selectDependentsForComponents true -schemaPrefix $RCUPREFIX -component OPSS -component IAU_VIEWER -component WEBCENTER -component MDS -component IAU_APPEND -component STB -component IAU -component WLS -f < /tmp/pwd.txt - /u01/oracle/oracle_common/bin/rcu -silent -createRepository -databaseType ORACLE -connectString $CONNECTION_STRING -dbUser sys -dbRole sysdba -useSamePasswordForAllSchemaUsers true -selectDependentsForComponents true -schemaPrefix $RCUPREFIX -component OPSS -component IAU_VIEWER -component WEBCENTER -component MDS -component IAU_APPEND -component STB -component IAU -component WLS -tablespace USERS -tempTablespace TEMP -f < /tmp/pwd.txt - #exit from the container - exit - + $ ./create-rcu-schema.sh \ + -s WCP1 \ + -t wcp \ + -d oracle-db.default.svc.cluster.local:1521/devpdb.k8s \ + -i oracle/wcportal:12.2.1.4\ + -n wcpns \ + -q Oradoc_db1 \ + -r welcome1 ``` Now the environment is ready to start the Oracle WebCenter Portal domain creation. @@ -662,7 +656,7 @@ Now the environment is ready to start the Oracle WebCenter Portal domain creatio #### 6.2 Create an Oracle WebCenter Portal domain -1. The sample scripts for Oracle WebCenter Portal domain deployment are available at `/kubernetes/samples/scripts/create-wcp-domain`. You must edit `create-domain-inputs.yaml` (or a copy of it) to provide the details for your domain. +1. The sample scripts for Oracle WebCenter Portal domain deployment are available at `create-wcp-domain`. You must edit `create-domain-inputs.yaml` (or a copy of it) to provide the details for your domain. Update `create-domain-inputs.yaml` with the following values for domain creation: @@ -671,7 +665,7 @@ Now the environment is ready to start the Oracle WebCenter Portal domain creatio 1. Run the `create-domain.sh` script to create a domain: ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv/ + $ cd ${WORKDIR}/create-wcp-domain/domain-home-on-pv/ $ ./create-domain.sh -i create-domain-inputs.yaml -o output ``` @@ -680,7 +674,7 @@ Now the environment is ready to start the Oracle WebCenter Portal domain creatio Once the `create-domain.sh` is successful, it generates `output/weblogic-domains/wcp-domain/domain.yaml`, which you can use to create the Kubernetes resource domain to start the domain and servers: ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv + $ cd ${WORKDIR}/create-wcp-domain/domain-home-on-pv $ kubectl create -f output/weblogic-domains/wcp-domain/domain.yaml ``` @@ -715,11 +709,11 @@ Watch the `wcpns` namespace for the status of domain creation: 1. Create an ingress for the domain in the domain namespace by using the sample Helm chart: ``` - $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ cd ${WORKDIR} helm install wcp-traefik-ingress \ - kubernetes/samples/charts/ingress-per-domain \ + charts/ingress-per-domain \ --namespace wcpns \ - --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --values charts/ingress-per-domain/values.yaml \ --set "traefik.hostname=$(hostname -f)" ``` 1. Verify the created ingress per domain details: diff --git a/docs-source/content/wcportal-domains/cleanup-domain-setup.md b/docs-source/content/wcportal-domains/cleanup-domain-setup.md index efbcf1b75..bb01ea653 100644 --- a/docs-source/content/wcportal-domains/cleanup-domain-setup.md +++ b/docs-source/content/wcportal-domains/cleanup-domain-setup.md @@ -11,7 +11,7 @@ To clean up the Oracle WebCenter Portal domain setup, follow the steps below. #### Delete the Generated Domain Home -To remove a domain home that you generated by running the `create-domain.sh` script in your production or testing environment, use the `delete-domain-job.yaml` file located at, `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv/output/weblogic-domains/wcp-domain>` directory. +To remove a domain home that you generated by running the `create-domain.sh` script in your production or testing environment, use the `delete-domain-job.yaml` file located at, `<$WORKDIR>/create-wcp-domain/domain-home-on-pv/output/weblogic-domains/wcp-domain>` directory. ``` $ kubectl create -f delete-domain-job.yaml diff --git a/docs-source/content/wcportal-domains/create-or-update-image/_index.md b/docs-source/content/wcportal-domains/create-or-update-image/_index.md index 287554423..b3b836a46 100644 --- a/docs-source/content/wcportal-domains/create-or-update-image/_index.md +++ b/docs-source/content/wcportal-domains/create-or-update-image/_index.md @@ -106,7 +106,7 @@ To create an Oracle WebCenter Portal Docker image using the WebLogic Image Tool, ```bash $ mkdir -p imagetool-setup/docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0 $ cd imagetool-setup/docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0 - $ cp -rf ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/imagetool-scripts/* . + $ cp -rf ${WORKDIR}/imagetool-scripts/* . ``` >Note: To create the image, continue with the following steps. To update the image, see [update an image](#update-an-image). @@ -226,6 +226,7 @@ The following files in the code repository location `/ --version=12.2.1.4.0 --tag=oracle/wcportal:12.2.1.4 --pull + --fromImage ghcr.io/oracle/oraclelinux:7-slim --additionalBuildCommands /docker-images/OracleWebCenterPortal/imagetool/12.2.1.4.0/additionalBuildCmds.txt --additionalBuildFiles /docker-images/OracleWebCenterPortal/dockerfiles/12.2.1.4/container-scripts --opatchBugNumber 28186730_13.9.4.2.5 @@ -236,7 +237,7 @@ The following files in the code repository location `/ > * `--version` value must match the `--version` value used in the `imagetool cache addInstaller` command for `--type wcp`. > * `--pull` always pulls the latest base Linux image `oraclelinux:7-slim` from the Docker registry. This flag can be removed if you want to use the Linux image `oraclelinux:7-slim`, which is already available on the host where the WCP image is created. - Refer to [this page](https://github.com/oracle/weblogic-image-tool/blob/master/site/create-image.md) for the complete list of options available with the WebLogic Image Tool `create` command. + Refer to [this page](https://oracle.github.io/weblogic-image-tool/userguide/tools/create-image/) for the complete list of options available with the WebLogic Image Tool `create` command. 1. Create the Oracle WebCenter Portal image: @@ -422,7 +423,7 @@ After [setting up the WebLogic Image Tool]({{< relref "/wcportal-domains/create- * `–-patches` - Multiple patches can be specified as a comma-separated list. * `--tag` - Specify the new tag to be applied for the image being built. - Refer [here](https://github.com/oracle/weblogic-image-tool/blob/master/site/update-image.md) for the complete list of options available with the WebLogic Image Tool `update` command. + Refer [here](https://oracle.github.io/weblogic-image-tool/userguide/tools/update-image/) for the complete list of options available with the WebLogic Image Tool `update` command. > Note: The WebLogic Image Tool cache should have the latest OPatch zip. The WebLogic Image Tool updates the OPatch if it is not already updated in the image. @@ -433,13 +434,13 @@ After [setting up the WebLogic Image Tool]({{< relref "/wcportal-domains/create- $ imagetool update --fromImage oracle/wcportal:12.2.1.4 --tag=wcportal:12.2.1.4-32224021 --patches=32224021_12.2.1.4.0 [INFO ] Image Tool build ID: 50f9b9aa-596c-4bae-bdff-c47c16b4c928 - [INFO ] Temporary directory used for docker build context: /scratch/asirasag/imagetoolcache/builddir/wlsimgbuilder_temp5130105621506307568 - [INFO ] Using patch 28186730_13.9.4.2.5 from cache: /home/asirasag/imagetool-setup/jars/p28186730_139425_Generic.zip + [INFO ] Temporary directory used for docker build context: /scratch/imagetoolcache/builddir/wlsimgbuilder_temp5130105621506307568 + [INFO ] Using patch 28186730_13.9.4.2.5 from cache: /home/imagetool-setup/jars/p28186730_139425_Generic.zip [INFO ] Updating OPatch in final image from version 13.9.4.2.1 to version 13.9.4.2.5 [WARNING] Skipping patch conflict check, no support credentials provided [WARNING] No credentials provided, skipping validation of patches - [INFO ] Using patch 32224021_12.2.1.4 from cache: /home/asirasag/imagetool-setup/jars/p32224021_122140_Generic.zip - [INFO ] docker cmd = docker build --no-cache --force-rm --tag wcportal:12.2.1.4-32224021 --build-arg http_proxy=http://www-proxy.us.oracle.com:80 --build-arg https_proxy=http://www-proxy.us.oracle.com:80 --build-arg no_proxy=localhost,127.0.0.0/8,.us.oracle.com,.oraclecorp.com,/var/run/docker.sock,100.111.157.155 /scratch/asirasag/imagetoolcache/builddir/wlsimgbuilder_temp5130105621506307568 + [INFO ] Using patch 32224021_12.2.1.4 from cache: /home/imagetool-setup/jars/p32224021_122140_Generic.zip + [INFO ] docker cmd = docker build --no-cache --force-rm --tag wcportal:12.2.1.4-32224021 --build-arg http_proxy=http:// --build-arg https_proxy=http:// --build-arg no_proxy=,/var/run/docker.sock /wlstmp/wlsimgbuilder_temp5130105621506307568 Sending build context to Docker daemon 192.4MB Step 1/9 : FROM oracle/wcportal:12.2.1.4 as final_build @@ -1087,13 +1088,13 @@ After [setting up the WebLogic Image Tool]({{< relref "/wcportal-domains/create- $ imagetool update --fromImage oracle/wcportal:12.2.1.4 --tag=wcportal:12.2.1.4-30761841 --patches=30761841_12.2.1.4.0 --dryRun [INFO ] Image Tool build ID: a473ba32-84b6-4374-9425-9e92ac90ee87 - [INFO ] Temporary directory used for docker build context: /scratch/asirasag/imagetoolcache/builddir/wlsimgbuilder_temp874401188519547557 - [INFO ] Using patch 28186730_13.9.4.2.5 from cache: /home/asirasag/imagetool-setup/jars/p28186730_139425_Generic.zip + [INFO ] Temporary directory used for docker build context: /scratch/imagetoolcache/builddir/wlsimgbuilder_temp874401188519547557 + [INFO ] Using patch 28186730_13.9.4.2.5 from cache: /home/imagetool-setup/jars/p28186730_139425_Generic.zip [INFO ] Updating OPatch in final image from version 13.9.4.2.1 to version 13.9.4.2.5 [WARNING] Skipping patch conflict check, no support credentials provided [WARNING] No credentials provided, skipping validation of patches - [INFO ] Using patch 32224021_12.2.1.4 from cache: /home/asirasag/imagetool-setup/jars/p32224021_122140_Generic.zip - [INFO ] docker cmd = docker build --no-cache --force-rm --tag wcportal:12.2.1.4-32224021 --build-arg http_proxy=http://www-proxy.us.oracle.com:80 --build-arg https_proxy=http://www-proxy.us.oracle.com:80 --build-arg no_proxy=localhost,127.0.0.0/8,.us.oracle.com,.oraclecorp.com,/var/run/docker.sock,100.111.157.155 /scratch/asirasag/imagetoolcache/builddir/wlsimgbuilder_temp874401188519547557 + [INFO ] Using patch 32224021_12.2.1.4 from cache: /home/imagetool-setup/jars/p32224021_122140_Generic.zip + [INFO ] docker cmd = docker build --no-cache --force-rm --tag wcportal:12.2.1.4-32224021 --build-arg http_proxy=http:// --build-arg https_proxy=http:// --build-arg no_proxy=,/var/run/docker.sock /wlstmp/wlsimgbuilder_temp874401188519547557 ########## BEGIN DOCKERFILE ########## # # Copyright (c) 2019, 2021, Oracle and/or its affiliates. diff --git a/docs-source/content/wcportal-domains/installguide/configure-wcp-search/_index.md b/docs-source/content/wcportal-domains/installguide/configure-wcp-search/_index.md index fc7315aac..21b55bd3c 100644 --- a/docs-source/content/wcportal-domains/installguide/configure-wcp-search/_index.md +++ b/docs-source/content/wcportal-domains/installguide/configure-wcp-search/_index.md @@ -18,7 +18,7 @@ description = "Set up search functionality in Oracle WebCenter Portal using Elas Elasticsearch is a highly scalable search engine. It allows you to store, search, and analyze big volumes of data quickly and provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON document. #### Set Up Persistent Volume and Persistent Volume Claim -Create a Kubernetes PV and PVC (Persistent Volume and Persistent Volume Claim) to store Elasticsearch data. To create PV and PVC, use the deployment YAML configuration file located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-pvpvc.yaml`. +Create a Kubernetes PV and PVC (Persistent Volume and Persistent Volume Claim) to store Elasticsearch data. To create PV and PVC, use the deployment YAML configuration file located at `${WORKDIR}/create-wcp-es-cluster/es-pvpvc.yaml`. ```yaml apiVersion: v1 @@ -54,7 +54,7 @@ To create PV & PVC run the below command: $ kubectl apply -f es-pvpvc.yaml ``` #### Create a Secret -To grant access to Oracle WebCenter Portal, create a Kubernetes secret using the deployment YAML configuration file located at `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-secret.yaml` +To grant access to Oracle WebCenter Portal, create a Kubernetes secret using the deployment YAML configuration file located at `${WORKDIR}/create-wcp-es-cluster/es-secret.yaml` ```yaml apiVersion: v1 @@ -79,7 +79,7 @@ To create Kubernetes Secret run the below command: $ kubectl apply -f es-secret.yaml ``` #### Headless Service - Each node in Elasticsearch cluster can communicate using a headless service. Create a headless service using the deployment YAML configuration file located at `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-service.yaml` to establish cluster communication. + Each node in Elasticsearch cluster can communicate using a headless service. Create a headless service using the deployment YAML configuration file located at `${WORKDIR}/create-wcp-es-cluster/es-service.yaml` to establish cluster communication. ```yaml apiVersion: v1 kind: Service @@ -104,7 +104,7 @@ To create Headless Service run below command: $ kubectl apply -f es-service.yaml ``` ### LoadBalancer -To access the Elasticsearch service outside of the Kubernetes cluster, create an external loadbalancer. Then access the Elasticsearch service by using the external IP of loadbalancer, create a loadbalancer using the deployment YAML configuration file located at `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-loadbalancer.yaml`. +To access the Elasticsearch service outside of the Kubernetes cluster, create an external loadbalancer. Then access the Elasticsearch service by using the external IP of loadbalancer, create a loadbalancer using the deployment YAML configuration file located at `${WORKDIR}/create-wcp-es-cluster/es-loadbalancer.yaml`. ```yaml apiVersion: v1 kind: Service @@ -134,7 +134,7 @@ $ kubectl get svc -n wcpns -l type=external ``` Make a note of the external IP from the above command and use this below sample URL to access Elasticsearch cluster health : http://externalIP:9200/_cluster/health #### Elasticsearch Cluster - Using the Kubernetes StatefulSet controller create an Elasticsearch Cluster comprising of three node using the deployment YAML configuration file located at `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-es-cluster/es-statefulset.yaml` + Using the Kubernetes StatefulSet controller create an Elasticsearch Cluster comprising of three node using the deployment YAML configuration file located at `${WORKDIR}/create-wcp-es-cluster/es-statefulset.yaml` ```yaml apiVersion: apps/v1 diff --git a/docs-source/content/wcportal-domains/installguide/create-wcp-domain/_index.md b/docs-source/content/wcportal-domains/installguide/create-wcp-domain/_index.md index 8e6d922f2..376bc627e 100644 --- a/docs-source/content/wcportal-domains/installguide/create-wcp-domain/_index.md +++ b/docs-source/content/wcportal-domains/installguide/create-wcp-domain/_index.md @@ -29,7 +29,7 @@ You can use the sample scripts to create a WebCenter Portal domain home on an ex If required, you can customize the parameters used for creating a domain in the `create-domain-inputs.yaml` file. -Please note that the sample scripts for the WebCenter Portal domain deployment are available from the previously downloaded repository at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/domain-home-on-pv/`. +Please note that the sample scripts for the WebCenter Portal domain deployment are available from the previously downloaded repository at `${WORKDIR}/create-wcp-domain/domain-home-on-pv/`. Make a copy of the `create-domain-inputs.yaml` file before updating the default values. @@ -38,6 +38,7 @@ The default domain created by the script has the following characteristics: * An Administration Server named `AdminServer` listening on port `7001`. * A configured cluster named `wcp-cluster` of size `5`. * Managed Server, named `wcpserver`, listening on port `8888`. +* If `configurePortletServer` is set to `true` . It configures a cluster named `wcportlet-cluster` of size `5` and Managed Server, named `wcportletserver`, listening on port `8889`. * Log files that are located in `/shared/logs/`. ##### Configuration parameters @@ -47,9 +48,11 @@ The following parameters can be provided in the inputs file: | --- | --- | --- | | `adminPort` | Port number for the Administration Server inside the Kubernetes cluster. | `7001` | | `sslEnabled` | SSL mode enabling flag | `false` | +| `configurePortletServer` |Configure portlet server cluster | `false` | | `adminServerSSLPort` | SSL Port number for the Administration Server inside the Kubernetes cluster. | `7002` | | `adminServerName` | Name of the Administration Server. | `AdminServer` | | `clusterName` | Name of the WebLogic cluster instance to generate for the domain. By default the cluster name is `wcp-cluster` for the WebCenter Portal domain. | `wcp-cluster` | +| `portletClusterName` | Name of the Portlet cluster instance to generate for the domain. By default the cluster name is `wcportlet-cluster` for the Portlet. | `wcportlet-cluster` | | `configuredManagedServerCount` | Number of Managed Server instances for the domain. | `5` | | `createDomainFilesDir` | Directory on the host machine to locate all the files that you need to create a WebLogic domain, including the script that is specified in the `createDomainScriptName` property. By default, this directory is set to the relative path `wlst`, and the *create script* uses the built-in WLST offline scripts in the `wlst` directory to create the WebLogic domain. An absolute path is also supported to point to an arbitrary directory in the file system. The built-in scripts can be replaced by the user-provided scripts or model files as long as those files are in the specified directory. Files in this directory are put into a Kubernetes config map, which in turn is mounted to `createDomainScriptsMountPath,` so that the Kubernetes pod can use the scripts and supporting files to create a domain home. | `wlst` | | `createDomainScriptsMountPath` | Mount path where the *create domain* scripts are located inside a pod. The `create-domain.sh` script creates a Kubernetes job to run the script (specified in the `createDomainScriptName` property) in a Kubernetes pod that creates a domain home. Files in the `createDomainFilesDir` directory are mounted to this location in the pod, so that the Kubernetes pod can use the scripts and supporting files to create a domain home. | `/u01/weblogic` | @@ -59,7 +62,7 @@ The following parameters can be provided in the inputs file: | `domainUID` | Unique ID that identifies this particular domain. Used as the name of the generated WebLogic domain as well as the name of the Kubernetes domain resource. This ID must be unique across all domains in a Kubernetes cluster. This ID cannot contain any character that is not valid in a Kubernetes service name. | `wcp-domain` | | `exposeAdminNodePort` | Boolean indicating if the Administration Server is exposed outside of the Kubernetes cluster. | `false` | | `exposeAdminT3Channel` | Boolean indicating if the T3 administrative channel is exposed outside the Kubernetes cluster. | `false` | -| `image` | WebCenter Portal Docker image. The WebLogic Kubernetes Operator requires WebCenter Portal release 12.2.1.4. Refer to [WebCenter Portal Docker Image](https://github.com/oracle/docker-images/tree/master/OracleWebCenterPortal) for details on how to obtain or create the image. | `oracle/wcportal:12.2.1.4` | +| `image` | WebCenter Portal Docker image. The WebLogic Kubernetes Operator requires WebCenter Portal release 12.2.1.4. Refer to [WebCenter Portal Docker Image](https://github.com/oracle/docker-images/tree/main/OracleWebCenterPortal) for details on how to obtain or create the image. | `oracle/wcportal:12.2.1.4` | | `imagePullPolicy` | WebLogic Docker image pull policy. Legal values are `IfNotPresent`, `Always`, or `Never` | `IfNotPresent` | | `imagePullSecretName` | Name of the Kubernetes secret to access the Docker Store to pull the WebLogic Server Docker image. The presence of the secret is validated when this parameter is specified. | | | `includeServerOutInPodLog` | Boolean indicating whether to include *server.out* to the pod's stdout. | `true` | @@ -67,20 +70,23 @@ The following parameters can be provided in the inputs file: | `javaOptions` | Java options for starting the Administration Server and Managed Servers. A Java option can include references to one or more of the following pre-defined variables to obtain WebLogic domain information: `$(DOMAIN_NAME)`, `$(DOMAIN_HOME)`, `$(ADMIN_NAME)`, `$(ADMIN_PORT)`, and `$(SERVER_NAME)`. | `-Dweblogic.StdoutDebugEnabled=false` | | `logHome` | The in-pod location for the domain log, server logs, server out, and Node Manager log files. `This field cannot be modified.` | `/u01/oracle/user_projects/logs/wcp-domain` | | `managedServerNameBase` | Base string used to generate Managed Server names. | `wcpserver` | -| `managedServerPort` | Port number for each Managed Server. | `8888` | -| `managedServerSSLPort` | SSL port number for each Managed Server. | `8889` | +| `portletServerNameBase` | Base string used to generate Portlet Server names. | `wcportletserver` | +| `managedServerPort` | Port number for each Managed Server. By default the managedServerPort is `8888` for the `wcpserver` and managedServerPort is `8889` for the `wcportletserver`. | `8888` | +| `managedServerSSLPort` | SSL port number for each Managed Server. By default the managedServerPort is `8788` for the wcpserver and managedServerPort is `8789` for the `wcportletserver`. | `8788` | +| `portletServerPort` |Port number for each Portlet Server. By default the portletServerPort is `8889` for the `wcportletserver`. | `8888` | +| `portletServerSSLPort` |SSL port number for each Portlet Server. By default the portletServerSSLPort is `8789` for the `wcportletserver`. | `8789` | | `namespace` | Kubernetes namespace in which to create the domain. | `wcpns` | | `persistentVolumeClaimName` | Name of the persistent volume claim created to host the domain home. If not specified, the value is derived from the `domainUID` as `-weblogic-sample-pvc`. | `wcp-domain-domain-pvc` | | `productionModeEnabled` | Boolean indicating if production mode is enabled for the domain. | `true` | | `serverStartPolicy` | Determines which WebLogic Server instances are to be started. Legal values are `NEVER`, `IF_NEEDED`, `ADMIN_ONLY`. | `IF_NEEDED` | | `t3ChannelPort` | Port for the T3 channel of the *NetworkAccessPoint*. | `30012` | | `t3PublicAddress` | Public address for the T3 channel. This should be set to the public address of the Kubernetes cluster. This would typically be a load balancer address.

For development environments only: In a single server (all-in-one) Kubernetes deployment, this may be set to the address of the master, or at the very least, it must be set to the address of one of the worker nodes. | If not provided, the script will attempt to set it to the IP address of the Kubernetes cluster. | -| `weblogicCredentialsSecretName` | Name of the Kubernetes secret for the Administration Server's user name and password. If not specified, then the value is derived from the `domainUID` as `-weblogic-credentials`. | wcpinfra-domain-credentials +| `weblogicCredentialsSecretName` | Name of the Kubernetes secret for the Administration Server's user name and password. If not specified, then the value is derived from the `domainUID` as `-weblogic-credentials`. | wcp-domain-domain-credentials | `weblogicImagePullSecretName` | Name of the Kubernetes secret for the Docker Store, used to pull the WebLogic Server image. | | | `serverPodCpuRequest`, `serverPodMemoryRequest`, `serverPodCpuCLimit`, `serverPodMemoryLimit` | The maximum amount of compute resources allowed and minimum amount of compute resources required for each server pod. Please refer to the Kubernetes documentation on `Managing Compute Resources for Containers` for details. | Resource requests and resource limits are not specified. Refer to [WebCenter Portal Cluster Sizing Recommendations](../pre-requisites/#webcenter-portal-cluster-sizing-recommendations) for more details. | | `rcuSchemaPrefix` | The schema prefix to use in the database, for example `WCP1`. You may wish to make this the same as the domainUID in order to simplify matching domain to their RCU schemas. | `WCP1` | | `rcuDatabaseURL` | The database URL. | `dbhostname:dbport/servicename` | -| `rcuCredentialsSecret` | The Kubernetes secret containing the database credentials. | `wcpinfra-rcu-credentials` | +| `rcuCredentialsSecret` | The Kubernetes secret containing the database credentials. | `wcp-domain-rcu-credentials` | | `loadBalancerHostName` | Host name for the final url accessible outside K8S environment. | `abc.def.com` | | `loadBalancerPortNumber` | Port for the final url accessible outside K8S environment. | `30305` | | `loadBalancerProtocol` | Protocol for the final url accessible outside K8S environment. | `http` | @@ -120,7 +126,7 @@ or `kubectl apply -f` command: 1. Run the `create-domain.sh` sample script, pointing it at the `create-domain-inputs.yaml` inputs file and an output directory like below: ```bash - $ cd <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/ + $ cd ${WORKDIR}/create-wcp-domain/ $ sh create-domain.sh -i create-domain-inputs.yaml -o output Input parameters being used export version="create-weblogic-sample-domain-inputs-v1" @@ -136,11 +142,13 @@ or `kubectl apply -f` command: export initialManagedServerReplicas="2" export managedServerNameBase="wcpserver" export managedServerPort="8888" - export managedServerSSLPort="8889" + export managedServerSSLPort="8788" + export portletServerPort="8889" + export portletServerSSLPort="8789" export image="oracle/wcportal:12.2.1.4" export imagePullPolicy="IfNotPresent" export productionModeEnabled="true" - export weblogicCredentialsSecretName="wcpinfra-domain-credentials" + export weblogicCredentialsSecretName="wcp-domain-domain-credentials" export includeServerOutInPodLog="true" export logHome="/u01/oracle/user_projects/domains/logs/$domainUID" export httpAccessLogInLogHome="true" @@ -157,7 +165,7 @@ or `kubectl apply -f` command: export createDomainFilesDir="wlst" export rcuSchemaPrefix="WCP1" export rcuDatabaseURL="oracle-db.wcpns.svc.cluster.local:1521/devpdb.k8s" - export rcuCredentialsSecret="wcpinfra-rcu-credentials" + export rcuCredentialsSecret="wcp-domain-rcu-credentials" export loadBalancerHostName="abc.def.com" export loadBalancerPortNumber="30305" export loadBalancerProtocol="http" @@ -167,7 +175,7 @@ or `kubectl apply -f` command: Generating output/weblogic-domains/wcp-domain/create-domain-job.yaml Generating output/weblogic-domains/wcp-domain/delete-domain-job.yaml Generating output/weblogic-domains/wcp-domain/domain.yaml - Checking to see if the secret wcpinfra-domain-credentials exists in namespace wcpns + Checking to see if the secret wcp-domain-domain-credentials exists in namespace wcpns configmap/wcp-domain-create-wcp-infra-sample-domain-job-cm created Checking the configmap wcp-domain-create-wcp-infra-sample-domain-job-cm was created configmap/wcp-domain-create-wcp-infra-sample-domain-job-cm labeled @@ -220,15 +228,15 @@ or `kubectl apply -f` command: The domain will be created using the script /u01/weblogic/create-domain-script.sh Initializing WebLogic Scripting Tool (WLST) ... - - + + Welcome to WebLogic Server Administration Scripting Shell - + Type help() for help on available commands - + ================================================================= - WebCenter Portal Weblogic Operator Domain Creation Script - 12.2.1.4.0 + WebCenter Portal Weblogic Operator Domain Creation Script + 12.2.1.4.0 ================================================================= Creating Base Domain... Creating Admin Server... @@ -239,6 +247,11 @@ or `kubectl apply -f` command: managed server name is wcpserver4 managed server name is wcpserver5 ['wcpserver1', 'wcpserver2', 'wcpserver3', 'wcpserver4', 'wcpserver5'] + Creating porlet cluster... + managed server name is wcportletserver1 + managed server name is wcportletserver2 + managed server name is wcportletserver3 + ['wcportletserver1', 'wcportletserver2', 'wcportletserver3', 'wcportletserver4', 'wcportletserver5'] Managed servers created... Creating Node Manager... Will create Base domain at /u01/oracle/user_projects/domains/wcp-domain @@ -261,16 +274,20 @@ or `kubectl apply -f` command: Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcpserver3 Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcpserver4 Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcpserver5 + Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcportletserver1 + Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcportletserver2 + Set CoherenceClusterSystemResource to defaultCoherenceCluster for server:wcportletserver3 Targeting Cluster ... Set CoherenceClusterSystemResource to defaultCoherenceCluster for cluster:wcp-cluster Set WLS clusters as target of defaultCoherenceCluster:wcp-cluster + Set CoherenceClusterSystemResource to defaultCoherenceCluster for cluster:wcportlet-cluster + Set WLS clusters as target of defaultCoherenceCluster:wcportlet-cluster Preparing to update domain... Jan 12, 2021 10:30:09 AM oracle.security.jps.az.internal.runtime.policy.AbstractPolicyImpl initializeReadStore INFO: Property for read store in parallel: oracle.security.jps.az.runtime.readstore.threads = null Domain updated successfully Domain Creation is done... - Successfully Completed - + Successfully Completed ``` #### Initialize the WebCenter Portal Domain @@ -306,12 +323,17 @@ pod/wcp-domain-adminserver 1/1 Running 0 pod/wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 0/1 Completed 0 3h12m pod/wcp-domain-wcp-server1 1/1 Running 0 11m pod/wcp-domain-wcp-server2 1/1 Running 0 11m +pod/wcp-domain-wcportletserver1 1/1 Running 1 21h + + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/wcp-domain-adminserver ClusterIP None 7001/TCP 13m +service/wcp-domain-cluster-wcp-cluster ClusterIP 10.98.145.173 8888/TCP 11m +service/wcp-domain-wcp-server1 ClusterIP None 8888/TCP 11m +service/wcp-domain-wcp-server2 ClusterIP None 8888/TCP 11m +service/wcp-domain-cluster-wcportlet-cluster ClusterIP 10.98.145.173 8889/TCP 11m +service/wcp-domain-wcportletserver1 ClusterIP None 8889/TCP 11m -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/wcp-domain-adminserver ClusterIP None 7001/TCP 13m -service/wcp-domain-cluster-wcp-cluster ClusterIP 10.98.145.173 8888/TCP 11m -service/wcp-domain-wcp-server1 ClusterIP None 8888/TCP 11m -service/wcp-domain-wcp-server2 ClusterIP None 8888/TCP 11m NAME COMPLETIONS DURATION AGE job.batch/wcp-domain-create-fmw-infra-sample-domain-job 1/1 16m 3h12m @@ -345,6 +367,8 @@ wcp-domain-adminserver 1/1 Running 0 wcp-domain-create-fmw-infra-sample-domain-job-8jr6k 0/1 Completed 0 3h14m wcp-domain-wcp-server1 1/1 Running 0 14m wcp-domain-wcp-server2 1/1 Running 0 14m +wcp-domain-wcportletserver1 1/1 Running 1 14m + ``` #### Verify the Services @@ -358,11 +382,14 @@ $ kubectl get services -n NAMESPACE Here is an example of the output of this command: ``` -bash-4.2$ kubectl get services -n wcpns -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -wcp-domain-adminserver ClusterIP None 7001/TCP 17m -wcp-domain-cluster-wcp-cluster ClusterIP 10.98.145.173 8888/TCP 14m -wcp-domain-wcp-server1 ClusterIP None 8888/TCP 14m -wcp-domain-wcp-server2 ClusterIP None 8888/TCP 14m +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +wcp-domain-adminserver ClusterIP None 7001/TCP 17m +wcp-domain-cluster-wcp-cluster ClusterIP 10.98.145.173 8888/TCP 14m +wcp-domain-wcp-server1 ClusterIP None 8888/TCP 14m +wcp-domain-wcp-server2 ClusterIP None 8888/TCP 14m +wcp-domain-cluster-wcportlet-cluster ClusterIP 10.98.145.173 8889/TCP 14m +wcp-domain-wcportletserver1 ClusterIP None 8889/TCP 14m + ``` #### Managing WebCenter Portal diff --git a/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md b/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md index 0eea74c32..edd9695ce 100644 --- a/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md +++ b/docs-source/content/wcportal-domains/installguide/prepare-your-environment/_index.md @@ -44,7 +44,7 @@ After creating Kubernetes clusters, you can optionally: ### Obtain the Oracle WebCenter Portal Docker Image The Oracle WebCenter Portal image with latest bundle patch and required interim patches can be obtained from My Oracle Support (MOS). This is the only image supported for production deployments. Follow the below steps to download the Oracle WebCenter Portal image from My Oracle Support. -1. Download patch [32688937](https://support.oracle.com/epmos/faces/ui/patch/PatchDetail.jspx?patchId=32688937) from My Oracle Support (MOS). +1. Download patch [33807917](https://support.oracle.com/epmos/faces/ui/patch/PatchDetail.jspx?patchId=33807917) from My Oracle Support (MOS). 1. Unzip the downloaded patch zip file. @@ -52,8 +52,8 @@ The Oracle WebCenter Portal image with latest bundle patch and required interim For example: ```bash - $ docker load < wcportal-12.2.1.4.0-210326.0857.320.tar - Loaded image: oracle/wcportal:12.2.1.4.0-210326.0857.320 + $ docker load < wcportal-12.2.1.4-jdk8-ol7-220203.0823.tar + Loaded image: oracle/wcportal:12.2.1.4-jdk8-ol7-220203.0823 ``` If you want to build and use an Oracle WebCenter Portal Docker image with any additional bundle patch or interim patches that are not part of the image obtained from My Oracle Support, then follow these [steps]({{< relref "/wcportal-domains/create-or-update-image/">}}) to create the image. @@ -81,7 +81,7 @@ $ docker login https://container-registry.oracle.com (enter your Oracle email Id WebLogic Kubernetes Operator image: ```bash -$ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.1.1 +$ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.3.0 ``` @@ -104,35 +104,19 @@ Oracle WebCenter Portal domain deployment on Kubernetes leverages the WebLogic K 1. Create a working directory to set up the source code. ```bash - $ export WORKDIR=$HOME/wcp_3.1.1 - $ mkdir - $ cd + $ mkdir $HOME/wcp_22.2.3 + $ cd $HOME/wcp_22.2.3 ``` -1. Download the supported version of WebLogic Kubernetes Operator source code archive file (`.zip`/`.tar.gz`) from the operator [relases page](https://github.com/oracle/weblogic-kubernetes-operator/releases). You can also download the supported operator version from [3.1.1](https://github.com/oracle/weblogic-kubernetes-operator/archive/v3.1.1.zip). - ```bash - $ git clone https://github.com/oracle/weblogic-kubernetes-operator.git --branch release/3.1.1 - ``` -1. Download the WebCenter Portal Kubernetes deployment scripts from this [repository](https://github.com/oracle/fmw-kubernetes.git) and copy them in to WebLogic operator samples location. +1. Download the Oracle WebCenter Portal Kubernetes deployment scripts from the Github [repository](https://github.com/oracle/fmw-kubernetes). Required artifacts are available at `OracleWeCenterPortal/kubernetes`. ```bash - $ git clone https://github.com/oracle/fmw-kubernetes.git --branch release/21.2.3 - - $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/create-wcp-domain ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ - $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/ingress-per-domain ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ - $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/create-wcp-es-cluster ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ - $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/imagetool-scripts ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ - $ cp -rf ${WORKDIR}/fmw-kubernetes/OracleWebCenterPortal/kubernetes/charts ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/ + $ git clone https://github.com/oracle/fmw-kubernetes.git + $ export WORKDIR=$HOME/wcp_22.2.3/fmw-kubernetes/OracleWebCenterPortal/kubernetes/ ``` -You can now use the deployment scripts from `<$WORKDIR>/weblogic-kubernetes-operator` to set up the WebCenter Portal domain as described later in this document. - -Your home directory for running all the required scripts: - -```bash -$ cd <$WORKDIR>/weblogic-kubernetes-operator -``` +You can now use the deployment scripts from `<$WORKDIR>` to set up the WebCenter Portal domain as described later in this document. ### Grant Roles and Clear Stale Resources @@ -179,7 +163,8 @@ $ cd <$WORKDIR>/weblogic-kubernetes-operator > Helm install weblogic-operator ```bash - $ helm install weblogic-kubernetes-operator kubernetes/charts/weblogic-operator --namespace operator-ns --set serviceAccount=operator-sa --set "domainNamespaces={}" --wait + $ cd ${WORKDIR} + $ helm install weblogic-kubernetes-operator charts/weblogic-operator --namespace operator-ns --set serviceAccount=operator-sa --set "domainNamespaces={}" --wait NAME: weblogic-kubernetes-operator LAST DEPLOYED: Wed Jan 6 01:47:33 2021 @@ -246,7 +231,7 @@ $ kubectl create namespace wcpns >Helm upgrade weblogic-operator ```bash $ helm upgrade --reuse-values --set "domainNamespaces={wcpns}" \ - --wait weblogic-kubernetes-operator kubernetes/charts/weblogic-operator --namespace operator-ns + --wait weblogic-kubernetes-operator charts/weblogic-operator --namespace operator-ns NAME: weblogic-kubernetes-operator LAST DEPLOYED: Wed Jan 6 01:52:58 2021 @@ -261,13 +246,12 @@ $ kubectl create namespace wcpns Using the create-weblogic-credentials script, create a Kubernetes secret that contains the user name and password for the domain in the same Kubernetes namespace as the domain: ```bash -$ sh kubernetes/samples/scripts/create-weblogic-domain-credentials/create-weblogic-credentials.sh \ - -u weblogic -p welcome1 -n wcpns \ - -d wcp-domain -s wcpinfra-domain-credentials + $ cd ${WORKDIR}/create-weblogic-domain-credentials + $ ./create-weblogic-credentials.sh -u weblogic -p welcome1 -n wcpns -d wcp-domain -s wcp-domain-domain-credentials - secret/wcpinfra-domain-credentials created - secret/wcpinfra-domain-credentials labeled - The secret wcpinfra-domain-credentials has been successfully created in the wcpns namespace. + secret/wcp-domain-domain-credentials created + secret/wcp-domain-domain-credentials labeled + The secret wcp-domain-domain-credentials has been successfully created in the wcpns namespace. ``` Where: @@ -275,23 +259,24 @@ $ sh kubernetes/samples/scripts/create-weblogic-domain-credentials/create-weblog * welcome1 is the weblogic password * wcp-domain is the domain name * wcpns is the domain namespace - * wcpinfra-domain-credentials is the secret name + * wcp-domain-domain-credentials is the secret name Note: You can inspect the credentials as follows: ```bash - $ kubectl get secret wcpinfra-domain-credentials -o yaml -n wcpns + $ kubectl get secret wcp-domain-domain-credentials -o yaml -n wcpns ``` #### Create a Kubernetes secret with the RCU credentials Create a Kubernetes secret for the Repository Configuration Utility (user name and password) using the `create-rcu-credentials.sh` script in the same Kubernetes namespace as the domain: ```bash - $ sh kubernetes/samples/scripts/create-rcu-credentials/create-rcu-credentials.sh \ + $ cd ${WORKDIR}/create-rcu-credentials + $ sh create-rcu-credentials.sh \ -u WCP1 -p welcome1 -a sys -q Oradoc_db1 -n wcpns \ - -d wcp-domain -s wcpinfra-rcu-credentials + -d wcp-domain -s wcp-domain-rcu-credentials - secret/wcpinfra-rcu-credentials created - secret/wcpinfra-rcu-credentials labeled - The secret wcpinfra-rcu-credentials has been successfully created in the wcpns namespace. + secret/wcp-domain-rcu-credentials created + secret/wcp-domain-rcu-credentials labeled + The secret wcp-domain-rcu-credentials has been successfully created in the wcpns namespace. ``` Where: @@ -300,12 +285,12 @@ $ sh kubernetes/samples/scripts/create-weblogic-domain-credentials/create-weblog * Oradoc_db1 is the database SYS users password * wcp-domain is the domain name * wcpns is the domain namespace - * wcpinfra-rcu-credentials is the secret name + * wcp-domain-rcu-credentials is the secret name Note: You can inspect the credentials as follows: ```bash - $ kubectl get secret wcpinfra-rcu-credentials -o yaml -n wcpns + $ kubectl get secret wcp-domain-rcu-credentials -o yaml -n wcpns ``` #### Create a persistent storage for an Oracle WebCenter Portal domain @@ -313,7 +298,7 @@ $ sh kubernetes/samples/scripts/create-weblogic-domain-credentials/create-weblog In the Kubernetes namespace you created, create the PV and PVC for the domain by running the [create-pv-pvc.sh](https://oracle.github.io/weblogic-kubernetes-operator/samples/simple/storage/) script. Follow the instructions for using the script to create a dedicated PV and PVC for the Oracle WebCenter Portal domain. - * Review the configuration parameters for PV creation [here](https://oracle.github.io/weblogic-kubernetes-operator/samples/simple/storage/#configuration-parameters). Based on your requirements, update the values in the `create-pv-pvc-inputs.yaml` file located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-weblogic-domain-pv-pvc/`. Sample configuration parameter values for an Oracle WebCenter Portal domain are: + * Review the configuration parameters for PV creation [here](https://oracle.github.io/weblogic-kubernetes-operator/samples/simple/storage/#configuration-parameters). Based on your requirements, update the values in the `create-pv-pvc-inputs.yaml` file located at `${WORKDIR}/create-weblogic-domain-pv-pvc/`. Sample configuration parameter values for an Oracle WebCenter Portal domain are: * `baseName`: domain * `domainUID`: wcp-domain * `namespace`: wcpns @@ -323,7 +308,7 @@ $ sh kubernetes/samples/scripts/create-weblogic-domain-credentials/create-weblog * Ensure that the path for the `weblogicDomainStoragePath` property exists (create one if it doesn't exist), that it has full access permissions, and that the folder is empty. * Run the `create-pv-pvc.sh` script: ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-weblogic-domain-pv-pvc + $ cd ${WORKDIR}/create-weblogic-domain-pv-pvc $ ./create-pv-pvc.sh -i create-pv-pvc-inputs.yaml -o output Input parameters being used export version="create-weblogic-sample-domain-pv-pvc-inputs-v1" @@ -355,19 +340,42 @@ For production deployments, you must set up and use a standalone (non-container) Before creating a domain, you need to set up the necessary schemas in your database. #### Run the Repository Creation Utility to set up your database schemas - Run a container to create Repository Creation Utility. + To create the database schemas for Oracle WebCenter Portal domain, run the create-rcu-schema.sh script. ```bash - $ kubectl run rcu --generator=run-pod/v1 --image oracle/wcportal:12.2.1.4 -n wcpns -- sleep infinity - #check the status of rcu pod - $ kubectl get pods -n wcpns - #make sure rcu pod status is running before executing this - $ kubectl exec -n wcpns -ti rcu /bin/bash - export CONNECTION_STRING=databasehostname:/ - export RCUPREFIX=WCP1 - echo -e "\n" > /tmp/pwd.txt - /u01/oracle/oracle_common/bin/rcu -silent -dropRepository -databaseType ORACLE -connectString $CONNECTION_STRING -dbUser sys -dbRole sysdba -selectDependentsForComponents true -schemaPrefix $RCUPREFIX -component OPSS -component IAU_VIEWER -component WEBCENTER -component MDS -component IAU_APPEND -component STB -component IAU -component WLS -component ACTIVITIES -f < /tmp/pwd.txt - /u01/oracle/oracle_common/bin/rcu -silent -createRepository -databaseType ORACLE -connectString $CONNECTION_STRING -dbUser sys -dbRole sysdba -useSamePasswordForAllSchemaUsers true -selectDependentsForComponents true -schemaPrefix $RCUPREFIX -component OPSS -component IAU_VIEWER -component WEBCENTER -component MDS -component IAU_APPEND -component STB -component IAU -component WLS -component ACTIVITIES -tablespace USERS -tempTablespace TEMP -f < /tmp/pwd.txt - #exit from the container - exit - ``` \ No newline at end of file + $ cd ${WORKDIR}/create-rcu-schema + $ sh create-rcu-schema.sh -h + usage: create-rcu-schema.sh -s -t -d -i -u -p -n -q -r -o [-h] + -s RCU Schema Prefix (required) + -t RCU Schema Type (optional) + (supported values: wcp(default), wcpp) + -d RCU Oracle Database URL (optional) + (default: oracle-db.default.svc.cluster.local:1521/devpdb.k8s) + -p FMW Infrastructure ImagePullSecret (optional) + (default: none) + -i Oracle WebCenter Portal Image (optional) + (default: oracle/wcportal:12.2.1.4) + -u FMW Infrastructure ImagePullPolicy (optional) + (default: IfNotPresent) + -n Namespace for RCU pod (optional) + (default: default) + -q password for database SYSDBA user. (optional) + (default: Oradoc_db1) + -r password for all schema owner (regular user). (optional) + (default: Oradoc_db1) + -o Output directory for the generated YAML file. (optional) + (default: rcuoutput) + -c Comma-separated variables in the format variablename=value. (optional). + (default: none) + -h Help + + $ ./create-rcu-schema.sh \ + -s WCP1 \ + -t wcp \ + -d oracle-db.default.svc.cluster.local:1521/devpdb.k8s \ + -i oracle/wcportal:12.2.1.4\ + -n wcpns \ + -q Oradoc_db1 \ + -r welcome1 + ``` +> Where RCU Schema type `wcp` generates webcenter portal related schema and `wcpp` generates webcenter portal plus portlet schemas. \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/installguide/prerequisites/_index.md b/docs-source/content/wcportal-domains/installguide/prerequisites/_index.md index c20f0f5bb..c706b05f7 100644 --- a/docs-source/content/wcportal-domains/installguide/prerequisites/_index.md +++ b/docs-source/content/wcportal-domains/installguide/prerequisites/_index.md @@ -19,11 +19,11 @@ Other than those considerations listed here, the WebCenter Portal domain works i In this release, WebCenter Portal domain is based on the `domain on a persistent volume` [model](https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/choosing-a-model/) where a WebCenter Portal domain is located in a persistent volume (PV). #### System Requirements -* Kubernetes 1.14.8+, 1.15.7+, 1.16.0+, 1.17.0+, and 1.18.0+ (check with `kubectl version`). -* Flannel networking v0.9.1-amd64 or later (check with `docker images | grep flannel`). -* Docker 18.9.1 or 19.03.1 (check with `docker version`). -* Helm 3.1.3+ (check with `helm version`). -* WebLogic Kubernetes operator 3.1.1 (see [the operator releases](https://github.com/oracle/weblogic-kubernetes-operator/releases/tag/v3.1.1) page). +* Kubernetes 1.18.18+, 1.19.7+, and 1.20.6+ (check with `kubectl version`). +* Flannel networking v0.14.0 or later (check with `docker images | grep flannel`), Calico networking v3.15. +* Docker 19.03.11+ (check with `docker version`). +* Helm 3.4+ (check with `helm version`). +* WebLogic Kubernetes operator 3.3.0 (see [the operator releases](https://github.com/oracle/weblogic-kubernetes-operator/releases/tag/v3.3.0) page). * Oracle WebCenter Portal 12.2.1.4.0 image. * These proxy setups are used for pulling the required binaries and source code from the respective repositories: * export NO_PROXY="localhost,127.0.0.0/8,$(hostname -i),.your-company.com,/var/run/docker.sock" @@ -43,7 +43,7 @@ following limitations currently exist for a WebCenter Portal domain: * `Domain in image` model is not supported in this version of the operator. * Only configured clusters are supported. Dynamic clusters are not supported on WebCenter Portal domains. Note that you can still use all of the scaling features. You just need to define the maximum size of your cluster at the time when you create a domain. * At present, WebCenter Portal doesn't run on non-Linux containers. -* Deploying and running a WebCenter Portal domain is supported only in the operator versions 3.1.1 and later. +* Deploying and running a WebCenter Portal domain is supported only in the operator versions 3.3.0 and later. * The [WebLogic Logging Exporter](https://github.com/oracle/weblogic-logging-exporter) currently supports WebLogic Server logs only. Other logs are not sent to Elasticsearch. Note, however, that you can use a sidecar with a log handling tool like Fluentd to get logs. * The [WebLogic Monitoring Exporter](https://github.com/oracle/weblogic-monitoring-exporter) diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/_index.md index 4cdf23135..720b12ad0 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/_index.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/_index.md @@ -7,7 +7,7 @@ pre = " " description = "Configure different load balancers for the Oracle WebCenter Portal domain." +++ -The WebLogic Kubernetes Operator supports ingress-based load balancers such as Traefik, NGINX (kubernetes/ingress-nginx) and Voyager. It also supports the Apache webtier load balancer. +The WebLogic Kubernetes Operator supports ingress-based load balancers such as Traefik and NGINX (kubernetes/ingress-nginx) . It also supports the Apache webtier load balancer. {{% children style="h4" description="true" %}} diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/apachewebtier.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/apachewebtier.md index f7948a7b7..d7d5262bf 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/apachewebtier.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/apachewebtier.md @@ -28,7 +28,7 @@ To build the Apache webtier Docker image, refer to the [sample](https://github.c {{%expand "Click here to see the sample content of the configuration file custom_mod_wl_apache.conf for wcp-domain domain" %}} ```bash -$ cat <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/charts/apache-samples/custom-sample/custom_mod_wl_apache.conf +$ cat ${WORKDIR}/charts/apache-samples/custom-sample/custom_mod_wl_apache.conf #Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. # @@ -76,16 +76,28 @@ WLSRequest On WebLogicCluster wcp-domain-cluster-wcp-cluster:8888 PathTrim /weblogic1 + + +WLSRequest On +WebLogicCluster wcp-domain-cluster-wcportlet-cluster:8889 +PathTrim /weblogic1 + + + +WLSRequest On +WebLogicCluster wcp-domain-cluster-wcportlet-cluster:8889 +PathTrim /weblogic1 + ``` {{% /expand %}} -1. Update `persistentVolumeClaimName` in `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/charts/apache-samples/custom-sample/input.yaml`with Persistence Volume which contains your own custom_mod_wl_apache.conf file. Use the PV/PVC created at the time of preparing environment, Copy the custom_mod_wl_apache.conf file to existing PersistantVolume. +1. Update `persistentVolumeClaimName` in `${WORKDIR}/charts/apache-samples/custom-sample/input.yaml`with Persistence Volume which contains your own custom_mod_wl_apache.conf file. Use the PV/PVC created at the time of preparing environment, Copy the custom_mod_wl_apache.conf file to existing PersistantVolume. #### Prepare the certificate and private key 1. (For the SSL termination configuration only) Run the following commands to generate your own certificate and private key using `openssl`. ```bash - $ cd <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/charts/apache-samples/custom-sample + $ cd ${WORKDIR}/charts/apache-samples/custom-sample $ export VIRTUAL_HOST_NAME=WEBLOGIC_HOST $ export SSL_CERT_FILE=WEBLOGIC_HOST.crt $ export SSL_CERT_KEY_FILE=WEBLOGIC_HOST.key @@ -121,7 +133,7 @@ PathTrim /weblogic1 $ touch input.yaml ``` - Update `virtualHostName` with the value of the `WEBLOGIC_HOST` in file `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/charts/apache-samples/custom-sample/input.yaml` + Update `virtualHostName` with the value of the `WEBLOGIC_HOST` in file `${WORKDIR}/charts/apache-samples/custom-sample/input.yaml` {{%expand "Click here to see the snapshot of the sample input.yaml file " %}} ```bash @@ -139,7 +151,7 @@ PathTrim /weblogic1 1. Install the Apache webtier Helm chart to the domain `wcpns` namespace with the specified input parameters: ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts + $ cd ${WORKDIR}/charts $ kubectl create namespace apache-webtier $ helm install apache-webtier --values apache-samples/custom-sample/input.yaml --namespace wcpns apache-webtier --set image=oracle/apache:12.2.1.3 ``` diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md index f1156e310..7a3396c0f 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/nginx.md @@ -105,20 +105,34 @@ Follow these steps to set up NGINX as a load balancer for an Oracle WebCenter Po #### Configure NGINX to manage ingresses -1. Create an ingress for the domain in the domain namespace by using the sample Helm chart. Here path-based routing is used for ingress. Sample values for default configuration are shown in the file `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/values.yaml`. By default, `type` is `TRAEFIK`, `tls` is `Non-SSL`. You can override these values by passing values through the command line or edit them in the sample `values.yaml` file. If needed, you can update the ingress YAML file to define more path rules (in section `spec.rules.host.http.paths`) based on the domain application URLs that need to be accessed. Update the template YAML file for the NGINX load balancer located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/templates/nginx-ingress.yaml` +1. Create an ingress for the domain in the domain namespace by using the sample Helm chart. Here path-based routing is used for ingress. Sample values for default configuration are shown in the file `${WORKDIR}/charts/ingress-per-domain/values.yaml`. By default, `type` is `TRAEFIK`, `tls` is `Non-SSL`. You can override these values by passing values through the command line or edit them in the sample `values.yaml` file. + +>NOTE: This is not an exhaustive list of rules. You can enhance it based on the application URLs that need to be accessed externally. + +If needed, you can update the ingress YAML file to define more path rules (in section `spec.rules.host.http.paths`) based on the domain application URLs that need to be accessed. Update the template YAML file for the NGINX load balancer located at `${WORKDIR}/charts/ingress-per-domain/templates/nginx-ingress.yaml` +You can add new path rules like shown below . +```yaml + - path: /NewPathRule + backend: + serviceName: 'Backend Service Name' + servicePort: 'Backend Service Port' + +``` + + ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator - $ helm install wcp-nginx-ingress kubernetes/samples/charts/ingress-per-domain \ + $ cd ${WORKDIR} + $ helm install wcp-domain-nginx charts/ingress-per-domain \ --namespace wcpns \ - --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --values charts/ingress-per-domain/values.yaml \ --set "nginx.hostname=$(hostname -f)" \ --set type=NGINX ``` Sample output: ```bash - NAME: wcp-nginx-ingress + NAME: wcp-domain-nginx LAST DEPLOYED: Fri Jul 24 09:34:03 2020 NAMESPACE: wcpns STATUS: deployed @@ -129,24 +143,24 @@ Follow these steps to set up NGINX as a load balancer for an Oracle WebCenter Po ```bash $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" - $ kubectl -n wcpns create secret tls domain1-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + $ kubectl -n wcpns create secret tls wcp-domain-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt ``` 1. Install `ingress-per-domain` using Helm for SSL configuration: ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator - $ helm install wcp-nginx-ingress kubernetes/samples/charts/ingress-per-domain \ + $ cd ${WORKDIR} + $ helm install wcp-domain-nginx charts/ingress-per-domain \ --namespace wcpns \ - --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --values charts/ingress-per-domain/values.yaml \ --set "nginx.hostname=$(hostname -f)" \ - --set type=NGINX --set tls=SSL + --set type=NGINX --set sslType=SSL ``` 1. For non-SSL access to the Oracle WebCenter Portal application, get the details of the services by the ingress: ```bash - $ kubectl describe ingress wcp-domain-ingress -n wcpns + $ kubectl describe ingress wcp-domain-nginx -n wcpns ``` {{%expand "Click here to see the sample output of the services supported by the above deployed ingress." %}} - Name: wcp-domain-ingress + Name: wcp-domain-nginx Namespace: wcpns Address: 10.101.123.106 Default backend: default-http-backend:80 () @@ -159,8 +173,10 @@ Follow these steps to set up NGINX as a load balancer for an Oracle WebCenter Po /rsscrawl wcp-domain-cluster-wcp-cluster:8888 (10.244.0.53:8888) /rest wcp-domain-cluster-wcp-cluster:8888 (10.244.0.53:8888) /webcenterhelp wcp-domain-cluster-wcp-cluster:8888 (10.244.0.53:8888) + /wsrp-tools wcp-domain-cluster-wcportlet-cluster:8889 (10.244.0.53:8889) + /portalTools wcp-domain-cluster-wcportlet-cluster:8889 (10.244.0.53:8889) /em wcp-domain-adminserver:7001 (10.244.0.51:7001) - Annotations: meta.helm.sh/release-name: wcp-nginx-ingress + Annotations: meta.helm.sh/release-name: wcp-domain-nginx meta.helm.sh/release-namespace: wcpns nginx.com/sticky-cookie-services: serviceName=wcp-domain-cluster-wcp-cluster srv_id expires=1h path=/; nginx.ingress.kubernetes.io/proxy-connect-timeout: 1800 @@ -175,15 +191,15 @@ Follow these steps to set up NGINX as a load balancer for an Oracle WebCenter Po 1. For SSL access to the Oracle WebCenter Portal application, get the details of the services by the above deployed ingress: ```bash - $ kubectl describe ingress wcp-domain-ingress -n wcpns + $ kubectl describe ingress wcp-domain-nginx -n wcpns ``` {{%expand "Click here to see the sample output of the services supported by the above deployed ingress." %}} - Name: wcp-domain-ingress + Name: wcp-domain-nginx Namespace: wcpns Address: 10.106.220.140 Default backend: default-http-backend:80 () TLS: - domain1-tls-cert terminates mydomain.com + wcp-domain-tls-cert terminates mydomain.com Rules: Host Path Backends ---- ---- -------- @@ -194,8 +210,10 @@ Follow these steps to set up NGINX as a load balancer for an Oracle WebCenter Po /webcenterhelp wcp-domain-cluster-wcp-cluster:8888 (10.244.0.43:8888,10.244.0.44:8888) /rest wcp-domain-cluster-wcp-cluster:8888 (10.244.0.43:8888,10.244.0.44:8888) /em wcp-domain-adminserver:7001 (10.244.0.42:7001) + /wsrp-tools wcp-domain-cluster-wcportlet-cluster:8889 (10.244.0.43:8889,10.244.0.44:8889) + /portalTools wcp-domain-cluster-wcportlet-cluster:8889 (10.244.0.43:8889,10.244.0.44:8889) Annotations: kubernetes.io/ingress.class: nginx - meta.helm.sh/release-name: wcp-nginx-ingress + meta.helm.sh/release-name: wcp-domain-nginx meta.helm.sh/release-namespace: wcpns nginx.ingress.kubernetes.io/affinity: cookie nginx.ingress.kubernetes.io/affinity-mode: persistent @@ -213,7 +231,7 @@ Follow these steps to set up NGINX as a load balancer for an Oracle WebCenter Po Events: {{% /expand %}} #### Verify non-SSL and SSL termination access -Verify that the Oracle WebCenter Portal domain application URLs are accessible through the ngnix NodePort `LOADBALANCER-NODEPORT` `30305`: +Verify that the Oracle WebCenter Portal domain application URLs are accessible through the nginx NodePort `LOADBALANCER-NODEPORT` `30305`: ```bash http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/console @@ -222,6 +240,8 @@ Verify that the Oracle WebCenter Portal domain application URLs are accessible t http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/rsscrawl http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/rest http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/webcenterhelp + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/wsrp-tools + http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-NODEPORT}/portalTools ``` @@ -232,7 +252,7 @@ Verify that the Oracle WebCenter Portal domain application URLs are accessible t Uninstall and delete the `ingress-nginx` deployment: ```bash - $ helm delete wcp-nginx-ingress -n wcpns + $ helm delete wcp-domain-nginx -n wcpns $ helm delete nginx-ingress -n wcpns ``` @@ -245,14 +265,14 @@ Uninstall and delete the `ingress-nginx` deployment: ```bash $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=domain1.org" - $ kubectl -n wcpns create secret tls domain1-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + $ kubectl -n wcpns create secret tls wcp-domain-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt ``` > Note: The value of `CN` is the host on which this ingress is to be deployed. 1. Deploy the ingress-nginx controller by using Helm on the domain namespace: ```bash $ helm install nginx-ingress -n wcpns \ - --set controller.extraArgs.default-ssl-certificate=wcpns/domain1-tls-cert \ + --set controller.extraArgs.default-ssl-certificate=wcpns/wcp-domain-tls-cert \ --set controller.service.type=NodePort \ --set controller.admissionWebhooks.enabled=false \ --set controller.extraArgs.enable-ssl-passthrough=true \ @@ -343,7 +363,7 @@ Uninstall and delete the `ingress-nginx` deployment: 1. Deploy the secured ingress: ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls + $ cd ${WORKDIR}/charts/ingress-per-domain/tls $ kubectl create -f nginx-tls.yaml ``` > Note: The default `nginx-tls.yaml` contains the backend for WebCenter Portal service with domainUID `wcp-domain`. You need to create similar tls configuration YAML files separately for each backend service. @@ -362,7 +382,7 @@ Uninstall and delete the `ingress-nginx` deployment: tls: - hosts: - domain1.org - secretName: domain1-tls-cert + secretName: wcp-domain-tls-cert rules: - host: domain1.org http: @@ -391,13 +411,15 @@ Verify that the Oracle WebCenter Portal domain application URLs are accessible t https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rest + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/wsrp-tools + https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/portalTools ``` #### Uninstall ingress-nginx tls ```bash - $ cd weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls + $ cd ${WORKDIR}/charts/ingress-per-domain/tls $ kubectl delete -f nginx-tls.yaml $ helm delete nginx-ingress -n wcpns ``` diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md index 09158b534..55a514876 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/traefik.md @@ -31,7 +31,7 @@ To load balance Oracle WebCenter Portal domain clusters, you can install the ing You can use the following `values.yaml` sample file and set kubernetes.namespaces as required. ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ cd ${WORKDIR} $ kubectl create namespace traefik $ helm repo add traefik https://containous.github.io/traefik-helm-chart ``` @@ -44,7 +44,7 @@ You can use the following `values.yaml` sample file and set kubernetes.namespac ```bash $ helm install traefik traefik/traefik \ --namespace traefik \ - --values kubernetes/samples/scripts/charts/traefik/values.yaml \ + --values charts/traefik/values.yaml \ --set "kubernetes.namespaces={traefik}" \ --set "service.type=NodePort" --wait ``` @@ -147,18 +147,28 @@ TEST SUITE: None #### Create an ingress for the domain Create an ingress for the domain in the domain namespace by using the sample Helm chart. Here path-based routing is used for ingress. -Sample values for default configuration are shown in the file `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/values.yaml`. +Sample values for default configuration are shown in the file `${WORKDIR}/charts/ingress-per-domain/values.yaml`. By default, `type` is `TRAEFIK` , `tls` is `Non-SSL`. You can override these values by passing values through the command line or edit them in the sample `values.yaml` file based on the type of configuration (non-SSL or SSL). -If needed, you can update the ingress YAML file to define more path rules (in section `spec.rules.host.http.paths`) based on the domain application URLs that need to be accessed. The template YAML file for the Traefik (ingress-based) load balancer is located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/templates/traefik-ingress.yaml` +>NOTE: This is not an exhaustive list of rules. You can enhance it based on the application URLs that need to be accessed externally. + +If needed, you can update the ingress YAML file to define more path rules (in section `spec.rules.host.http.paths`) based on the domain application URLs that need to be accessed. The template YAML file for the Traefik (ingress-based) load balancer is located at `${WORKDIR}/charts/ingress-per-domain/templates/traefik-ingress.yaml` +You can add new path rules like shown below . +```yaml + - path: /NewPathRule + backend: + serviceName: 'Backend Service Name' + servicePort: 'Backend Service Port' +``` + 1. Install `ingress-per-domain` using Helm for non-SSL configuration: ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ cd ${WORKDIR} $ helm install wcp-traefik-ingress \ - kubernetes/samples/charts/ingress-per-domain \ + charts/ingress-per-domain \ --namespace wcpns \ - --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --values charts/ingress-per-domain/values.yaml \ --set "traefik.hostname=$(hostname -f)" ``` Sample output: @@ -175,27 +185,10 @@ If needed, you can update the ingress YAML file to define more path rules (in se ```bash $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" - $ kubectl -n wcpns create secret tls wcpinfra-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt + $ kubectl -n wcpns create secret tls wcp-domain-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt ``` > Note: The value of `CN` is the host on which this ingress is to be deployed. -1. Create a Traefik Middleware custom resource - - In case of SSL termination, Traefik must pass a custom header `WL-Proxy-SSL:true` to the WebLogic Server endpoints. Create the Middleware using the following command: - ```bash - $ cat <-@kubernetescrd`. ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ cd ${WORKDIR} $ helm install wcp-traefik-ingress \ - kubernetes/samples/charts/ingress-per-domain \ + charts/ingress-per-domain \ --namespace wcpns \ - --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ + --values charts/ingress-per-domain/values.yaml \ --set "traefik.hostname=$(hostname -f)" \ - --set tls=SSL + --set sslType=SSL ``` Sample output: ```bash @@ -267,6 +260,8 @@ If needed, you can update the ingress YAML file to define more path rules (in se /rest wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) /webcenterhelp wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) /em wcp-domain-adminserver:7001 (10.244.0.51:7001) + /wsrp-tools wcp-domain-cluster-wcportlet-cluster:8889 (10.244.0.52:8889,10.244.0.53:8889) + /portalTools wcp-domain-cluster-wcportlet-cluster:8889 (10.244.0.52:8889,10.244.0.53:8889) Annotations: kubernetes.io/ingress.class: traefik meta.helm.sh/release-name: wcp-traefik-ingress meta.helm.sh/release-namespace: wcpns @@ -286,7 +281,7 @@ Namespace: wcpns Address: Default backend: default-http-backend:80 () TLS: - wcpinfra-tls-cert terminates www.example.com + wcp-domain-tls-cert terminates www.example.com Rules: Host Path Backends ---- ---- -------- @@ -297,6 +292,8 @@ Rules: /rest wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) /webcenterhelp wcp-domain-cluster-wcp-cluster:8888 (10.244.0.52:8888,10.244.0.53:8888) /em wcp-domain-adminserver:7001 (10.244.0.51:7001) + /wsrp-tools wcp-domain-cluster-wcportlet-cluster:8889 (10.244.0.52:8889,10.244.0.53:8889) + /portalTools wcp-domain-cluster-wcportlet-cluster:8889 (10.244.0.52:8889,10.244.0.53:8889) Annotations: kubernetes.io/ingress.class: traefik meta.helm.sh/release-name: wcp-traefik-ingress meta.helm.sh/release-namespace: wcpns @@ -338,6 +335,8 @@ After setting up the Traefik (ingress-based) load balancer, verify that the doma http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rsscrawl http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rest http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenterhelp + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/wsrp-tools + http://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/portalTools ``` @@ -352,6 +351,9 @@ After setting up the Traefik (ingress-based) load balancer, verify that the doma https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/rest https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/wsrp-tools + https://${LOADBALANCER_HOSTNAME}:${LOADBALANCER-SSLPORT}/portalTools + ``` @@ -371,7 +373,7 @@ $ helm delete wcp-traefik-ingress -n wcpns 1. Use Helm to install the Traefik (ingress-based) load balancer. You can use the `values.yaml` sample file and set kubernetes.namespaces as required. ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator + $ cd ${WORKDIR} $ kubectl create namespace traefik $ helm repo add traefik https://containous.github.io/traefik-helm-chart ``` @@ -384,7 +386,7 @@ $ helm delete wcp-traefik-ingress -n wcpns ```bash $ helm install traefik traefik/traefik \ --namespace traefik \ - --values kubernetes/samples/scripts/charts/traefik/values.yaml \ + --values charts/traefik/values.yaml \ --set "kubernetes.namespaces={traefik}" \ --set "service.type=NodePort" --wait ``` @@ -447,7 +449,7 @@ $ helm upgrade traefik traefik/traefik --namespace traefik --reuse-values \ #### Create IngressRouteTCP 1. For each backend service, create different ingresses, as Traefik does not support multiple paths or rules with annotation `ssl-passthrough`. For example, for `wcp-domain-adminserver` and `wcp-domain-cluster-wcp-cluster,` different ingresses must be created. -1. To enable SSL passthrough in Traefik, you can configure a TCP router. A sample YAML for `IngressRouteTCP` is available at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls/traefik-tls.yaml`. The following should be updated in `traefik-tls.yaml`: +1. To enable SSL passthrough in Traefik, you can configure a TCP router. A sample YAML for `IngressRouteTCP` is available at `${WORKDIR}/charts/ingress-per-domain/tls/traefik-tls.yaml`. The following should be updated in `traefik-tls.yaml`: * The service name and the SSL port should be updated in the `services`. * The load balancer host name should be updated in the `HostSNI` rule. @@ -491,6 +493,6 @@ Verify the access to application URLs exposed through the configured service. Th ```bash $ helm delete traefik -n traefik - $ cd weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls + $ cd ${WORKDIR}/charts/ingress-per-domain/tls $ kubectl delete -f traefik-tls.yaml ``` diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/voyager.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/voyager.md deleted file mode 100644 index 42d33aed0..000000000 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/configure-load-balancer/voyager.md +++ /dev/null @@ -1,526 +0,0 @@ -+++ -title = "Voyager" -date = 2019-02-22T15:44:42-05:00 -draft = false -weight = 3 -pre = "c. " -description = "Configure the ingress-based Voyager load balancer for an Oracle WebCenter Portal domain." -+++ - -*Voyager/HAProxy* is a popular ingress-based load balancer for production environments. -You can install and configure *Voyager/HAProxy* to load balance Oracle WebCenter Portal domain clusters and configure it for non-SSL, SSL termination, and end-to-end SSL access of the application URL. -Follow these steps to set up Voyager as a load balancer for an Oracle WebCenter Portal domain in a Kubernetes cluster: - -* [ Non-SSL and SSL termination](#non-ssl-and-ssl-termination) - - 1. [Install the Voyager load balancer](#install-the-voyager-load-balancer) - 2. [Configure Voyager to manage ingresses](#configure-voyager-to-manage-ingresses) - 3. [Verify non-SSL and SSL access](#verify-non-ssl-and-ssl-access) - -* [ End-to-end SSL configuration](#end-to-end-ssl-configuration) - 1. [Install Voyager load balancer for end-to-end SSL](#install-voyager-load-balancer-for-end-to-end-ssl) - 2. [Deploy tls to access the services](#deploy-tls-to-access-services) - 3. [Verify end-to-end SSL access](#verify-end-to-end-ssl-access) - -#### Non-SSL and SSL termination - -##### Install the Voyager load balancer - -1. Add the AppsCode chart repository: - - ```bash - $ helm repo add appscode https://charts.appscode.com/stable/ - $ helm repo update - ``` -1. Verify that the chart repository has been added: - - ```bash - $ helm search repo appscode/voyager - ``` - > **NOTE**: After updating the Helm repository, the Voyager version listed may be newer that the one shown here. Check with the Voyager site for the latest supported versions. - -1. Install the Voyager operator: - - > **NOTE**: The Voyager version you install must match the version found with the helm search. - - ```bash - $ kubectl create namespace voyager - $ helm install voyager-operator appscode/voyager --version 10.0.0 \ - --namespace voyager \ - --set cloudProvider=baremetal \ - --set apiserver.enableValidatingWebhook=false - ``` - - Wait until the Voyager operator is running. - -1. Check the status of the Voyager operator: - ```bash - $ kubectl get all -n voyager - ``` - {{%expand "Click here to see the sample output." %}} - - NAME READY STATUS RESTARTS AGE - pod/voyager-operator-b84f95f8f-4szhl 1/1 Running 0 43h - - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - service/voyager-operator ClusterIP 10.107.201.155 443/TCP,56791/TCP 43h - - NAME READY UP-TO-DATE AVAILABLE AGE - deployment.apps/voyager-operator 1/1 1 1 43h - - NAME DESIRED CURRENT READY AGE - replicaset.apps/voyager-operator-b84f95f8f 1 1 1 43h - - {{% /expand %}} - - See the official [installation document](https://github.com/oracle/weblogic-kubernetes-operator/blob/master/kubernetes/samples/charts/voyager/README.md#a-step-by-step-guide-to-install-the-voyager-operator) for more details. - -1. Update the Voyager operator. - Once the Voyager operator is installed, and it is running, upgrade it using the `helm upgrade` command. In this command, `voyager` is the Voyager namespace and `wcpns` is the namespace of the domain. - - ```bash - $ helm upgrade voyager-operator appscode/voyager --namespace voyager - ``` - {{%expand "Click here to see the sample output." %}} - Release "voyager-operator" has been upgraded. Happy Helming! - NAME: voyager-operator - LAST DEPLOYED: Mon Sep 28 11:53:43 2020 - NAMESPACE: voyager - STATUS: deployed - REVISION: 2 - TEST SUITE: None - NOTES: - Set cloudProvider for installing Voyager - - To verify that Voyager has started, run: - - kubectl get deployment --namespace voyager -l "app.kubernetes.io/name=voyager,app.kubernetes.io/instance=voyager-operator" - - {{% /expand %}} - -##### Configure Voyager to manage ingresses - -1. Create an ingress for the domain in the domain namespace by using the sample Helm chart. Here path-based routing is used for ingress. Sample values for default configuration are shown in the file `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/values.yaml`. By default, `type` is `TRAEFIK` , `tls` is `Non-SSL`. You can override these values by passing your values through the command line or edit the existing values in the sample `values.yaml` file. - - If needed, you can update the ingress yaml file to define more path rules (in the `spec.rules.host.http.paths` section) based on the domain application URLs that need to be accessed. You need to update the template yaml file for the Voyager (ingress-based) load balancer located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/templates/voyager-ingress.yaml` - - ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator - $ helm install wcp-voyager-ingress kubernetes/samples/charts/ingress-per-domain \ - --namespace wcpns \ - --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ - --set type=VOYAGER - ``` - {{%expand "Click here to check the output of the ingress per domain " %}} - ```bash - NAME: wcp-voyager-ingress - LAST DEPLOYED: Mon Jul 20 08:20:27 2020 - NAMESPACE: wcpns - STATUS: deployed - REVISION: 1 - TEST SUITE: None - ``` - {{% /expand %}} -1. For secured access (SSL) to the Oracle WebCenter Portal application, create a certificate and generate secrets: - ```bash - $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" - $ kubectl -n wcpns create secret tls wcpinfra-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt - ``` - > Note: The value of `CN` is the host on which this ingress is to be deployed. - -1. Deploy `ingress-per-domain` using Helm for SSL configuration. - - If needed, you can update the ingress yaml file to define more path rules (in the `spec.rules.host.http.paths section`) based on the domain application URLs that need to be accessed. You need to update the template yaml file for the Voyager (ingress-based) load balancer located at `${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/templates/voyager-ingress.yaml` - - ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator - $ helm install wcp-voyager-ingress kubernetes/samples/charts/ingress-per-domain \ - --namespace wcpns \ - --values kubernetes/samples/charts/ingress-per-domain/values.yaml \ - --set type=VOYAGER \ - --set tls=SSL - ``` - {{%expand "Click here to see the sample output of the above Commnad." %}} - ```bash - NAME: wcp-voyager-ingress - LAST DEPLOYED: Mon Jul 20 08:20:27 2020 - NAMESPACE: wcpns - STATUS: deployed - REVISION: 1 - TEST SUITE: None - ``` - {{% /expand %}} - -1. For non-SSL access to the Oracle WebCenter Portal application, get the details of the services deployed by the above ingress: - - ```bash - $ kubectl describe ingress.voyager.appscode.com/wcp-domain-voyager -n wcpns - ``` - {{%expand "Click here to see the sample output of the services supported by the above deployed ingress." %}} - Sample output: - ```bash - Name: wcp-domain-voyager - Namespace: wcpns - Labels: app.kubernetes.io/managed-by=Helm - Annotations: ingress.appscode.com/affinity: cookie - ingress.appscode.com/stats: true - ingress.appscode.com/type: NodePort - meta.helm.sh/release-name: wcp-voyager-ingress - meta.helm.sh/release-namespace: wcpns - API Version: voyager.appscode.com/v1beta1 - Kind: Ingress - Metadata: - Creation Timestamp: 2021-01-13T08:19:16Z - Generation: 1 - Managed Fields: - API Version: voyager.appscode.com/v1beta1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:ingress.appscode.com/affinity: - f:ingress.appscode.com/stats: - f:ingress.appscode.com/type: - f:meta.helm.sh/release-name: - f:meta.helm.sh/release-namespace: - f:labels: - .: - f:app.kubernetes.io/managed-by: - f:spec: - .: - f:rules: - Manager: Go-http-client - Operation: Update - Time: 2021-01-13T08:19:16Z - Resource Version: 340890 - Self Link: /apis/voyager.appscode.com/v1beta1/namespaces/wcpns/ingresses/wcp-domain-voyager - UID: a06315c2-23ad-4916-a972-cd3555494eb8 - Spec: - Rules: - Host: * - Http: - Node Port: 30305 - Paths: - Backend: - Service Name: wcp-domain-cluster-wcp-cluster - Service Port: 8888 - Path: /webcenter - Backend: - Service Name: wcp-domain-adminserver - Service Port: 7001 - Path: /console - Backend: - Service Name: wcp-domain-cluster-wcp-cluster - Service Port: 8888 - Path: /rsscrawl - Backend: - Service Name: wcp-domain-adminserver - Service Port: 7001 - Path: /em - Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal ServiceReconcileSuccessful 62s voyager-operator Successfully created NodePort Service voyager-wcp-domain-voyager - Normal ConfigMapReconcileSuccessful 62s voyager-operator Successfully created ConfigMap voyager-wcp-domain-voyager - Normal RBACSuccessful 62s voyager-operator Successfully created ServiceAccount voyager-wcp-domain-voyager - Normal RBACSuccessful 62s voyager-operator Successfully created Role voyager-wcp-domain-voyager - Normal RBACSuccessful 62s voyager-operator Successfully created RoleBinding voyager-wcp-domain-voyager - Normal DeploymentReconcileSuccessful 62s voyager-operator Successfully created HAProxy Deployment voyager-wcp-domain-voyager - Normal StatsServiceReconcileSuccessful 62s voyager-operator Successfully created stats Service voyager-wcp-domain-voyager-stats - - ``` - {{% /expand %}} - -1. For SSL access to the Oracle WebCenter Portal application, get the details of the services by the above deployed ingress: - - ```bash - $ kubectl describe ingress.voyager.appscode.com/wcp-domain-voyager -n wcpns - ``` - {{%expand "Click here to see all the services configured by the above deployed ingress." %}} - - ```bash - Name: wcp-domain-voyager - Namespace: wcpns - Labels: app.kubernetes.io/managed-by=Helm - Annotations: ingress.appscode.com/affinity: cookie - ingress.appscode.com/stats: true - ingress.appscode.com/type: NodePort - meta.helm.sh/release-name: wcp-domain-ingress - meta.helm.sh/release-namespace: wcpns - API Version: voyager.appscode.com/v1beta1 - Kind: Ingress - Metadata: - Creation Timestamp: 2021-01-15T05:40:20Z - Generation: 1 - Managed Fields: - API Version: voyager.appscode.com/v1beta1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:ingress.appscode.com/affinity: - f:ingress.appscode.com/stats: - f:ingress.appscode.com/type: - f:meta.helm.sh/release-name: - f:meta.helm.sh/release-namespace: - f:labels: - .: - f:app.kubernetes.io/managed-by: - f:spec: - .: - f:frontendRules: - f:rules: - f:tls: - Manager: Go-http-client - Operation: Update - Time: 2021-01-15T05:40:20Z - Resource Version: 704682 - Self Link: /apis/voyager.appscode.com/v1beta1/namespaces/wcpns/ingresses/wcp-domain-voyager - UID: 1e83c6a6-336f-4e29-b38a-023e00ca5cd5 - Spec: - Frontend Rules: - Port: 443 - Rules: - http-request set-header WL-Proxy-SSL true - Rules: - Host: * - Http: - Node Port: 30305 - Paths: - Backend: - Service Name: wcp-domain-cluster-wcp-cluster - Service Port: 8888 - Path: /webcenter - Backend: - Service Name: wcp-domain-adminserver - Service Port: 7001 - Path: /console - Backend: - Service Name: wcp-domain-cluster-wcp-cluster - Service Port: 8888 - Path: /rsscrawl - Backend: - Service Name: wcp-domain-cluster-wcp-cluster - Service Port: 8888 - Path: /rest - Backend: - Service Name: wcp-domain-cluster-wcp-cluster - Service Port: 8888 - Path: /webcenterhelp - Backend: - Service Name: wcp-domain-adminserver - Service Port: 7001 - Path: /em - Tls: - Hosts: - * - Secret Name: domain1-tls-cert - Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal ServiceReconcileSuccessful 54s voyager-operator Successfully created NodePort Service voyager-wcp-domain-voyager - Normal ConfigMapReconcileSuccessful 54s voyager-operator Successfully created ConfigMap voyager-wcp-domain-voyager - Normal RBACSuccessful 54s voyager-operator Successfully created ServiceAccount voyager-wcp-domain-voyager - Normal RBACSuccessful 54s voyager-operator Successfully created Role voyager-wcp-domain-voyager - Normal RBACSuccessful 54s voyager-operator Successfully created RoleBinding voyager-wcp-domain-voyager - Normal DeploymentReconcileSuccessful 54s voyager-operator Successfully created HAProxy Deployment voyager-wcp-domain-voyager - Normal StatsServiceReconcileSuccessful 54s voyager-operator Successfully created stats Service voyager-wcp-domain-voyager-stats - - ``` - {{% /expand %}} - - - -##### Verify Non-SSL and SSL access - -After setting up the Voyager (ingress-based) load balancer, verify that the Oracle WebCenter Portal domain applications are accessible through the load balancer port 30305 (both SSL and non-SSL). The application URLs for Oracle WebCenter Portal domain are: - -> Note: Port 30305 is the LOADBALANCER-Non-SSLPORT and LOADBALANCER-SSLPORT. - -##### Non-SSL configuration - - ```bash - http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenter - http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/console - http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/em - http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rsscrawl - http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/rest - http://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-Non-SSLPORT}/webcenterhelp - - ``` -##### SSL configuration - - ```bash - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenter - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/console - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/em - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rest - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp - - ``` - -##### Uninstall the chart - - To uninstall and delete the my-ingress deployment, enter the following command: - - ```bash - $ helm delete wcp-voyager-ingress -n wcpns - $ helm delete voyager-operator -n voyager - - ``` - -#### End-to-end SSL configuration - -##### Install Voyager load balancer for end-to-end SSL - -Install the Voyager load balancer as described [here](#install-the-voyager-load-balancer). - -1. Check the status of the Voyager operator. - - ```bash - $ kubectl get all -n voyager - ``` - Sample output: - - ```bash - NAME READY STATUS RESTARTS AGE - pod/voyager-operator-b84f95f8f-4szhl 1/1 Running 0 43h - - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - service/voyager-operator ClusterIP 10.107.201.155 443/TCP,56791/TCP 43h - - NAME READY UP-TO-DATE AVAILABLE AGE - deployment.apps/voyager-operator 1/1 1 1 43h - - NAME DESIRED CURRENT READY AGE - replicaset.apps/voyager-operator-b84f95f8f 1 1 1 43h - ``` -1. For secured access (SSL) to the Oracle WebCenter Portal application, create a certificate and generate Kuberentes secrets: - ```bash - $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls1.key -out /tmp/tls1.crt -subj "/CN=*" - $ kubectl -n wcpns create secret tls domain1-tls-cert --key /tmp/tls1.key --cert /tmp/tls1.crt - ``` -##### Deploy tls to access services - -1. Deploy tls to securely access the services. Only one application can be configured with ssl-passthrough. A sample tls file for Voyager is shown below for the service `wcp-domain-cluster-wcp-cluster` and port `8889`. All the applications running on port `8889` can be securely accessed through this ingress. For each backend service, create different ingresses as Voyager does not support multiple path/rules with annotation `ssl-passthrough`. - - ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls - ``` - {{%expand "Click here to see the content of the file voyager-tls.yaml" %}} - ```bash - apiVersion: voyager.appscode.com/v1beta1 - kind: Ingress - metadata: - name: voyager-ssl - namespace: wcpns - annotations: - ingress.appscode.com/type: 'NodePort' - ingress.appscode.com/stats: 'true' - ingress.appscode.com/affinity: 'cookie' - ingress.appscode.com/ssl-passthrough: "true" - spec: - tls: - - secretName: domain1-tls-cert - hosts: - - '*' - rules: - - host: '*' - http: - nodePort: '31443' - paths: - - path: / - backend: - serviceName: wcp-domain-cluster-wcp-cluster - servicePort: '8889' - - ``` - {{% /expand %}} - ```bash - $ kubectl create -f voyager-tls.yaml - ``` - {{%expand "Click here to see the services supported by the ingress" %}} - ```bash - kubectl describe ingress.voyager.appscode.com/voyager-ssl -n wcpns - Name: voyager-ssl - Namespace: wcpns - Labels: - Annotations: ingress.appscode.com/affinity: cookie - ingress.appscode.com/ssl-passthrough: true - ingress.appscode.com/stats: true - ingress.appscode.com/type: NodePort - API Version: voyager.appscode.com/v1beta1 - Kind: Ingress - Metadata: - Creation Timestamp: 2020-07-20T04:34:05Z - Generation: 1 - Managed Fields: - API Version: voyager.appscode.com/v1beta1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:ingress.appscode.com/affinity: - f:ingress.appscode.com/ssl-passthrough: - f:ingress.appscode.com/stats: - f:ingress.appscode.com/type: - f:spec: - .: - f:rules: - f:tls: - Manager: kubectl - Operation: Update - Time: 2020-07-20T04:34:05Z - Resource Version: 340071 - Self Link: /apis/voyager.appscode.com/v1beta1/namespaces/wcpns/ingresses/voyager-ssl - UID: 4a9b2e02-1593-45b3-8ac4-ae1ac0f2832c - Spec: - Rules: - Host: * - Http: - Node Port: 31443 - Paths: - Backend: - Service Name: wcp-domain-cluster-wcp-cluster - Service Port: 8889 - Path: / - Tls: - Hosts: - * - Secret Name: domain1-tls-cert - Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal ServiceReconcileSuccessful 7m37s voyager-operator Successfully created NodePort Service voyager-voyager-ssl - N ormal ConfigMapReconcileSuccessful 7m37s voyager-operator Successfully created ConfigMap voyager-voyager-ssl - Normal RBACSuccessful 7m37s voyager-operator Successfully created ServiceAccount voyager-voyager-ssl - Normal RBACSuccessful 7m37s voyager-operator Successfully created Role voyager-voyager-ssl - Normal RBACSuccessful 7m37s voyager-operator Successfully created RoleBinding voyager-voyager-ssl - Normal DeploymentReconcileSuccessful 7m37s voyager-operator Successfully created HAProxy Deployment voyager-voyager-ssl - Normal StatsServiceReconcileSuccessful 7m37s voyager-operator Successfully created stats Service voyager-voyager-ssl-stats - Normal DeploymentReconcileSuccessful 3m5s voyager-operator Successfully patched HAProxy Deployment voyager-voyager-ssl - ``` - {{% /expand %}} - -##### Verify end-to-end SSL access - -Verify that the Oracle WebCenter Portal domain application URLs are accessible through the SSLPORT `31443`: - ```bash - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenter - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rsscrawl - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/webcenterhelp - https://${LOADBALANCER-HOSTNAME}:${LOADBALANCER-SSLPORT}/rest - - ``` - -##### Uninstall the Voyager tls - - ```bash - $ cd ${WORKDIR}/weblogic-kubernetes-operator/kubernetes/samples/charts/ingress-per-domain/tls - $ kubectl delete -f voyager-tls.yaml - $ helm delete voyager-operator -n voyager - ``` diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/_index.md index 356bb1382..abd6ac875 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/_index.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/_index.md @@ -9,278 +9,112 @@ You can monitor a WebCenter Portal domain using Prometheus and Grafana by export ### Prerequisites This document assumes that the Prometheus Operator is deployed on the Kubernetes cluster. If it is not already deployed, follow the steps below for deploying the Prometheus Operator. +### Prepare to use the setup monitoring script -#### Clone the kube-prometheus project -Refer to the compatibility matrix of [Kube Prometheus](https://github.com/coreos/kube-prometheus#kubernetes-compatibility-matrix) and clone the [release](https://github.com/coreos/kube-prometheus/releases) version of the `kube-prometheus` repository according to the Kubernetes version of your cluster. -$ git clone https://github.com/coreos/kube-prometheus.git -``` - -#### Label the nodes -Kube-Prometheus requires all the exporter nodes to be labelled with `kubernetes.io/os=linux`. If a node is not labelled, then you must label it using the following command: +The sample scripts for setup monitoring for OracleWebCenterPortal domain are available at `${WORKDIR}/monitoring-service`. -``` -$ kubectl label nodes --all kubernetes.io/os=linux -``` +You must edit `monitoring-inputs.yaml`(or a copy of it) to provide the details of your domain. Refer to the configuration parameters below to understand the information that you must provide in this file. -#### Create Prometheus and Grafana resources +#### Configuration parameters -Change to the `kube-prometheus` directory and execute the following commands to create the namespace and CRDs: +The following parameters can be provided in the inputs file. -**NOTE**: Wait for a minute for each command to process. +| Parameter | Description | Default | +| --- | --- | --- | +| `domainUID` | domainUID of the OracleWebCenterPortal domain. | `wcp-domain` | +| `domainNamespace` | Kubernetes namespace of the OracleWebCenterPortal domain. | `wcpns` | +| `setupKubePrometheusStack` | Boolean value indicating whether kube-prometheus-stack (Prometheus, Grafana and Alertmanager) to be installed | `true` | +| `additionalParamForKubePrometheusStack` | The script install's kube-prometheus-stack with `service.type` as NodePort and values for `service.nodePort` as per the parameters defined in `monitoring-inputs.yaml`. Use `additionalParamForKubePrometheusStack` parameter to further configure with additional parameters as per [values.yaml](https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/values.yaml). Sample value to disable NodeExporter, Prometheus-Operator TLS support and Admission webhook support for PrometheusRules resources is `--set nodeExporter.enabled=false --set prometheusOperator.tls.enabled=false --set prometheusOperator.admissionWebhooks.enabled=false`| | +| `monitoringNamespace` | Kubernetes namespace for monitoring setup. | `monitoring` | +| `adminServerName` | Name of the Administration Server. | `AdminServer` | +| `adminServerPort` | Port number for the Administration Server inside the Kubernetes cluster. | `7001` | +| `wcpClusterName` | Name of the wcpCluster. | `wcp_cluster` | +| `wcpManagedServerPort` | Port number of the managed servers in the wcpCluster. | `8888` | +| `wlsMonitoringExporterTowcpCluster` | Boolean value indicating whether to deploy WebLogic Monitoring Exporter to wcpCluster. | `false` | +| `wcpPortletClusterName` | Name of the wcpPortletCluster. | `wcportlet-cluster` | +| `wcpManagedServerPort` | Port number of the Portlet managed servers in the wcpPortletCluster. | `8889` | +| `wlsMonitoringExporterTowcpPortletCluster` | Boolean value indicating whether to deploy WebLogic Monitoring Exporter to wcpPortletCluster. | `false` | +| `exposeMonitoringNodePort` | Boolean value indicating if the Monitoring Services (Prometheus, Grafana and Alertmanager) is exposed outside of the Kubernetes cluster. | `false` | +| `prometheusNodePort` | Port number of the Prometheus outside the Kubernetes cluster. | `32101` | +| `grafanaNodePort` | Port number of the Grafana outside the Kubernetes cluster. | `32100` | +| `alertmanagerNodePort` | Port number of the Alertmanager outside the Kubernetes cluster. | `32102` | +| `weblogicCredentialsSecretName` | Name of the Kubernetes secret which has Administration Server’s user name and password. | `wcp-domain-domain-credentials` | -```bash -$ cd kube-prometheus +Note that the values specified in the `monitoring-inputs.yaml` file will be used to install kube-prometheus-stack (Prometheus, Grafana and Alertmanager) and deploying WebLogic Monitoring Exporter into the OracleWebCenterPortal domain. Hence make the domain specific values to be same as that used during domain creation. -$ kubectl create -f manifests/setup -$ until kubectl get servicemonitors --all-namespaces ; do date; sleep 1; echo ""; done -$ kubectl create -f manifests/ -``` +### Run the setup monitoring script -#### Provide external access -To provide external access for Grafana, Prometheus, and Alertmanager, execute the commands below: +Update the values in `monitoring-inputs.yaml` as per your requirement and run the `setup-monitoring.sh` script, specifying your inputs file: ```bash -$ kubectl patch svc grafana -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32100 }]' -$ kubectl patch svc prometheus-k8s -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32101 }]' -$ kubectl patch svc alertmanager-main -n monitoring --type=json -p '[{"op": "replace", "path": "/spec/type", "value": "NodePort" },{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 32102 }]' +$ cd ${WORKDIR}/monitoring-service +$ ./setup-monitoring.sh \ + -i monitoring-inputs.yaml ``` +The script will perform the following steps: -**NOTE**: - -* `32100` is the external port for Grafana -* `32101` is the external port for Prometheus -* `32102` is the external port for Alertmanager - --------------- +- Helm install `prometheus-community/kube-prometheus-stack` of version "16.5.0" if `setupKubePrometheusStack` is set to `true`. +- Deploys WebLogic Monitoring Exporter to Administration Server. +- Deploys WebLogic Monitoring Exporter to `wcpCluster` if `wlsMonitoringExporterTowcpCluster` is set to `true`. +- Deploys WebLogic Monitoring Exporter to `wcpPortletCluster` if `wlsMonitoringExporterTowcpPortletCluster` is set to `true`. +- Exposes the Monitoring Services (Prometheus at `32101`, Grafana at `32100` and Alertmanager at `32102`) outside of the Kubernetes cluster if `exposeMonitoringNodePort` is set to `true`. +- Imports the WebLogic Server Grafana Dashboard if `setupKubePrometheusStack` is set to `true`. -## Set Up the WebLogic Monitoring Exporter +### Verify the results +The setup monitoring script will report failure if there was any error. However, verify that required resources were created by the script. -Set up the WebLogic Monitoring Exporter to collect WebLogic Server metrics and monitor your WebCenter Portal domain. +#### Verify the kube-prometheus-stack -#### Generate the WebLogic Monitoring Exporter Deployment Package - -Two packages are required as the listening ports are different for the Administration Server and Managed Servers. -One binary required for the Admin Server (`wls-exporter-as.war`) and one for Managed Cluster (`wls-exporter-ms.war`). -Set the required proxies and then run the script `getX.X.X.sh` to generate two binaries: +To confirm that `prometheus-community/kube-prometheus-stack` was installed when `setupKubePrometheusStack` is set to `true`, run the following command: ```bash -$ cd <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter - -$ sh get1.1.0.sh -``` - -Output: +$ helm ls -n monitoring ``` - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed -100 607 0 607 0 0 357 0 --:--:-- 0:00:01 --:--:-- 357 -100 2016k 100 2016k 0 0 398k 0 0:00:05 0:00:05 --:--:-- 797k --------------------wls-exporter-ms start------------------- -created /tmp/ci-GNysQzP1kv -Copying completed -/tmp/ci-GNysQzP1kv <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter -in temp dir - adding: WEB-INF/weblogic.xml (deflated 66%) - adding: config.yml (deflated 63%) -wls-exporter-ms.war is ready --------------------wls-exporter-ms end------------------- --------------------wls-exporter-as start------------------- -Copying completed -in temp dir - adding: WEB-INF/weblogic.xml (deflated 66%) - adding: config.yml (deflated 52%) -wls-exporter-as.war is ready --------------------wls-exporter-as end------------------- -zip completed -<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter -``` - -#### Copy the WAR Files to the WebLogic Domain Home - -Copy the `wls-exporter-as.war` and `wls-exporter-ms.war` files to the domain home directory in the Administration Server pod. +Sample output: +```bash +$ helm ls -n monitoring +NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION +monitoring monitoring 1 2021-06-18 12:58:35.177221969 +0000 UTC deployed kube-prometheus-stack-16.5.0 0.48.0 +$ ``` -$ kubectl cp wls-exporter-as.war wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/ - -$ kubectl cp wls-exporter-ms.war wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/ -``` - -#### Deploy the WebLogic Monitoring Exporter - -Follow these steps to deploy the package in the WebLogic Server instances: - -1. On the Administration Server and Managed Servers, deploy the WebLogic Monitoring Exporter (`wls-exporter-ms.war`) separately using the Oracle Enterprise Manager. - - ![Wme-Deploy](images/wme-deploy.png) - -1. Select the servers to which the Exporter WAR should be deployed: - - ![Wme-Deploy-Target-Server](images/wme-deploy-target-server.png) - -1. Set the application name. The application name must be different if it is deployed separately in the Administration Server and Managed Servers. Make sure the context-root for both the deployments is `wls-exporter`: - - ![Wme-Deploy-Contextroot](images/wme-deploy-contextroot.png) - -1. Click **Install and start application**. - -1. Then deploy the WebLogic Monitoring Exporter application (`wls-exporter-ms.war`). - -1. Activate the changes to start the application. If the application is started and the port is exposed, -then you can access the WebLogic Monitoring Exporter console using this URL: `http:///wls-exporter`. - ![Wme-Test-Url](images/wme-test-url.png) +#### Verify the Prometheus, Grafana and Alertmanager setup -1. Repeat same steps for `wls-exporter-as.war`. +When `exposeMonitoringNodePort` was set to `true`, verify that monitoring services are accessible outside of the Kubernetes cluster: + +- `32100` is the external port for Grafana and with credentials `admin:admin` +- `32101` is the external port for Prometheus +- `32102` is the external port for Alertmanager -#### Configure Prometheus Operator -Prometheus enables you to collect metrics from the WebLogic Monitoring Exporter. The Prometheus Operator identifies the targets using service discovery. In order to Prometheus be able to discovery and scrape services inside the additional namespaces like `wcpns`, you must create a service monitor resource pointing to the services in `wcpns` namespace. +#### Verify the service discovery of WebLogic Monitoring Exporter -See the following sample service monitor deployment YAML configuration file located at +Verify whether prometheus is able to discover wls-exporter and collect the metrics: -`<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml`. +1. Access the Prometheus dashboard at http://mycompany.com:32101/ -`ServiceMonitor` for wls-exporter: -``` -apiVersion: v1 -kind: Secret -metadata: - name: basic-auth - namespace: monitoring -data: - password: d2VsY29tZTEK # welcome1 i.e.'WebLogic password' - user: d2VibG9naWM= # weblogic i.e. 'WebLogic username' -type: Opaque ---- -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: wls-exporter-wcp-domain - namespace: monitoring - labels: - k8s-app: wls-exporter -spec: - namespaceSelector: - matchNames: - - wcpns - selector: - matchLabels: - weblogic.domainName: wcp-domain - endpoints: - - basicAuth: - password: - name: basic-auth - key: password - username: - name: basic-auth - key: user - port: default - relabelings: - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - interval: 10s - honorLabels: true - path: /wls-exporter/metrics -``` +1. Navigate to Status to see the Service Discovery details. -To export metrics using `wls-exporter,` you need to set basicAuth in Prometheus. So create a Kubernetes `Secret` with the user name and password that are `base64` encoded. This Secret will be used in the ServiceMonitor deployment. +1. Verify that wls-exporter is listed in the discovered services. -When generating the base64 encoded strings for the user name and password, observe if a new line character is appended in the encoded string. This line character causes an authentication failure. To avoid a new line string, use the following example: +#### Verify the WebLogic Server dashoard -``` -$ echo -n "Welcome1" | base64 -V2VsY29tZTE= -``` +You can access the Grafana dashboard at http://mycompany.com:32100/. -In the deployment YAML configuration for `wls-exporter` shown above, `weblogic.domainName: wcp-domain` is used as a label under `spec.selector.matchLabels`, so all the services are selected for the service monitor. If you don't use this label, you should create separate service monitors for each server--if the server name is used as matching labels in `spec.selector.matchLabels`. Doing so will require you to relabel the configuration because Prometheus, by default, ignores the labels provided in the *wls-exporter*. +1. Log in to Grafana dashboard with username: `admin` and password: `admin`. -By default, Prometheus does not store all the labels provided by the target. In the service monitor deployment YAML configuration, you must mention the relabeling configuration (`spec.endpoints.relabelings`) so that certain labels provided by `weblogic-monitoring-exporter` (required for the Grafana dashboard) are stored in Prometheus. Do not delete the following section from the configuration YAML file: -``` -relabelings: - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) -``` +1. Navigate to "WebLogic Server Dashboard" under General and verify. -#### Add `RoleBinding` and `Role` for the WebLogic Domain Namespace + This displays the WebLogic Server Dashboard. -The RoleBinding is required for Prometheus to access the endpoints provided by the WebLogic Monitoring Exporter. You need to add RoleBinding for the namespace under which the WebLogic Servers pods are running in the Kubernetes cluster. Edit the `kube-prometheus/manifests/prometheus-roleBindingSpecificNamespaces.yaml` file in the Prometheus Operator deployment manifests and add the `RoleBinding` for the namespace (`wcpns`) similar to the following example: + ![Wme-GP-WLS-Dashboard](images/wcp-graphana-dashboard.png) -``` -- apiVersion: rbac.authorization.k8s.io/v1 - kind: RoleBinding - metadata: - name: prometheus-k8s - namespace: wcpns - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: prometheus-k8s - subjects: - - kind: ServiceAccount - name: prometheus-k8s - namespace: monitoring -``` -In the Prometheus Operator deployment manifests located at `kube-prometheus/manifests/prometheus-roleSpecificNamespaces.yaml,` add the `Role` for the namespace `wcpns` under which the WebLogic Servers pods are running in the Kubernetes cluster. See the following example: -``` -- apiVersion: rbac.authorization.k8s.io/v1 - kind: Role - metadata: - name: prometheus-k8s - namespace: wcpns - rules: - - apiGroups: - - "" - resources: - - services - - endpoints - - pods - verbs: - - get - - list - - watch -``` -Then apply `prometheus-roleBindingSpecificNamespaces.yaml` and `prometheus-roleSpecificNamespaces.yaml` for the `RoleBinding` and `Role` to take effect in the cluster. -``` -$ kubectl apply -f kube-prometheus/manifests/prometheus-roleBindingSpecificNamespaces.yaml +### Delete the monitoring setup -$ kubectl apply -f kube-prometheus/manifests/prometheus-roleSpecificNamespaces.yaml -``` -#### Deploy the Service Monitor +To delete the monitoring setup created by [Run the setup monitoring script](#run-the-setup-monitoring-script), run the below command: -To deploy the service monitor, use the above `wls-exporter.yaml` deployment YAML and run the following command: -``` -$ kubectl create -f <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-monitoring-exporter/wls-exporter.yaml +```bash +$ cd ${WORKDIR}/monitoring-service +$ ./delete-monitoring.sh \ + -i monitoring-inputs.yaml ``` -#### Enable Prometheus to Discover the Service - -After deploying the service monitor, Prometheus should be able to discover *wls-exporter* and export metrics. - -You can access the Prometheus dashboard at `http://mycompany.com:32101/`. - -![Wme-Service-Discovery](images/wme-service-discovery.png) - - -#### Deploy Grafana Dashboard - -To view the domain metrics, deploy the Grafana dashboard provided in the [WebLogic Monitoring Exporter](https://github.com/oracle/weblogic-monitoring-exporter/tree/master/samples/kubernetes/end2end#monitoring-weblogic-server-with-the-grafana-dashboard). - -You can access the Grafana dashboard at `http://mycompany.com:32100/`. - -1. Log in to Grafana dashboard with `admin/admin`. -1. Go to **Settings**, then select **DataSources**, and then **Add Data Source**. - - HTTP URL: Prometheus URL `http://mycompany.com:32101/` - - Auth: Enable Basic Auth - - Basic Auth Details: Weblogic credentials provided in the step [Configure Prometheus Operator](#configure-prometheus-operator) - - ![Wme-GP-Add-Datasource](images/wme-gp-add-datasource.png) - -1. Download the `weblogic_dashboard.json` file from [here](weblogic_dashboard.json). -1. Click **Add** and then **Import**. Paste the modified JSON in the **Paste JSON** block, and then load it. - - ![Wme-GP-Import-Json](images/wme-gp-import-json.png) - - This displays the WebLogic Server Dashboard. - - ![Wme-GP-WLS-Dashboard](images/wcp-graphana-dashboard.png) \ No newline at end of file diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/_index.md index 297d4d4ac..e57909b7d 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/_index.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/_index.md @@ -7,5 +7,5 @@ pre = " " description = "Publish WebLogic Server logs into Elasticsearch." +++ -To publish WebLogic Server logs into Elasticsearch, you can configure your WebCenter Portal domain to use Fluentd or WebLogic Logging Exporter. +To publish WebLogic Server logs into Elasticsearch, you can configure your WebCenter Portal domain to use Fluentd, WebLogic Logging Exporter or Logstash. {{% children style="h4" description="true" %}} diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/_index.md index bbb1c6213..e9baec49e 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/_index.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/fluentd/_index.md @@ -24,7 +24,7 @@ A complete example of a domain definition with fluentd configuration is at the [ {{% notice note %}} These identifiers are used in the sample commands. * `wcpns`: WebCenter Portal domain namespace * `wcp-domain`: `domainUID` -* `wcpinfra-domain-credentials`: Kubernetes secret +* `wcp-domain-domain-credentials`: Kubernetes secret {{%/notice %}} The sample Elasticsearch configuration is: @@ -70,7 +70,7 @@ spec: #### Add Elasticsearch secrets to WebLogic domain credentials Configure the `fluentd` container to look for Elasticsearch parameters in the domain credentials. Edit the domain credentials and add the parameters shown in the example below. -For example, run: `kubectl edit secret wcpinfra-domain-credentials -n wcpns` and add the base64 encoded values of each Elasticsearch parameter: +For example, run: `kubectl edit secret wcp-domain-domain-credentials -n wcpns` and add the base64 encoded values of each Elasticsearch parameter: ```text elasticsearchhost: ZWxhc3RpY3NlYXJjaC5ib2JzLWJvb2tzLnNhbXBsZS5jb20= elasticsearchport: NDQz @@ -165,7 +165,7 @@ Add a container to the domain to run `fluentd` in the Administration Server and The container definition: * Defines a `LOG_PATH` environment variable that points to the log location of `bobbys-front-end`. -* Defines `ELASTICSEARCH_HOST`, `ELASTICSEARCH_PORT`, `ELASTICSEARCH_USER`, and `ELASTICSEARCH_PASSWORD` environment variables that are all retrieving their values from the secret `wcpinfra-domain-credentials`. +* Defines `ELASTICSEARCH_HOST`, `ELASTICSEARCH_PORT`, `ELASTICSEARCH_USER`, and `ELASTICSEARCH_PASSWORD` environment variables that are all retrieving their values from the secret `wcp-domain-domain-credentials`. * Includes volume mounts for the `fluentd-config` `ConfigMap` and the volume containing the domain logs. **NOTE**: For brevity, only the paths to the relevant configuration are shown. @@ -197,23 +197,23 @@ spec: valueFrom: secretKeyRef: key: elasticsearchhost - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials - name: ELASTICSEARCH_PORT valueFrom: secretKeyRef: key: elasticsearchport - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials - name: ELASTICSEARCH_USER valueFrom: secretKeyRef: key: elasticsearchuser - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials optional: true - name: ELASTICSEARCH_PASSWORD valueFrom: secretKeyRef: key: elasticsearchpassword - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials optional: true image: fluent/fluentd-kubernetes-daemonset:v1.3.3-debian-elasticsearch-1.3 imagePullPolicy: IfNotPresent @@ -259,7 +259,7 @@ spec: image: "oracle/wcportal:12.2.1.4" imagePullPolicy: "IfNotPresent" webLogicCredentialsSecret: - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials includeServerOutInPodLog: true logHomeEnabled: true httpAccessLogInLogHome: true @@ -309,22 +309,22 @@ spec: valueFrom: secretKeyRef: key: elasticsearchport - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials - name: ELASTICSEARCH_PORT valueFrom: secretKeyRef: key: elasticsearchhost - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials - name: ELASTICSEARCH_USER valueFrom: secretKeyRef: key: elasticsearchuser - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials - name: ELASTICSEARCH_PASSWORD valueFrom: secretKeyRef: key: elasticsearchpassword - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials image: fluent/fluentd-kubernetes-daemonset:v1.11.5-debian-elasticsearch6-1.0 imagePullPolicy: IfNotPresent name: fluentd @@ -355,7 +355,7 @@ spec: name: fluentd-config-volume serverStartPolicy: IF_NEEDED webLogicCredentialsSecret: - name: wcpinfra-domain-credentials + name: wcp-domain-domain-credentials ``` ##### Get the Kibana dashboard port information as shown below: diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/_index.md b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/_index.md index dcf52cb72..2c2a084a7 100644 --- a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/_index.md +++ b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/publishing-logs/weblogiclogging/_index.md @@ -92,7 +92,7 @@ $ kubectl cp setDomainEnv.sh wcpns/wcp-domain-adminserver:/u01/oracle/user_proje #### Create a Configuration File for the WebLogic Logging Exporter -1. Specify the Elasticsearch server host and port number in the file: `<$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml` +1. Specify the Elasticsearch server host and port number in the file: `<$WORKDIR>/logging-services/weblogic-logging-exporter/WebLogicLoggingExporter.yaml` Example: ``` @@ -107,14 +107,9 @@ $ kubectl cp setDomainEnv.sh wcpns/wcp-domain-adminserver:/u01/oracle/user_proje 2. Copy the `WebLogicLoggingExporter.yaml` file to the domain home directory in the WebLogic Administration Server pod: ```bash -$ kubectl cp <$WORKDIR>/weblogic-kubernetes-operator/kubernetes/samples/scripts/create-wcp-domain/utils/weblogic-logging-exporter/WebLogicLoggingExporter.yaml wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/config/ +$ kubectl cp <$WORKDIR>/logging-services/weblogic-logging-exporter/WebLogicLoggingExporter.yaml wcpns/wcp-domain-adminserver:/u01/oracle/user_projects/domains/wcp-domain/config/ ``` -#### Edit the WebCenter Portal ingress (Only for Voyager Loadbalancer) - -By default, paths for wls-exporter are commented in the ingress template. In order to expose the wls-exporter end-point externally, you must edit the WebCenter Portal ingress reapply them if necessary. (See `Using Voyager Loadbalacer`) - - #### Restart the Servers in the Domain To restart the servers, stop and then start them using the following commands: diff --git a/docs-source/content/wcportal-domains/release-notes.md b/docs-source/content/wcportal-domains/release-notes.md index 1d076c0af..75d304443 100644 --- a/docs-source/content/wcportal-domains/release-notes.md +++ b/docs-source/content/wcportal-domains/release-notes.md @@ -9,5 +9,6 @@ pre: "1. " | Date | Version | Change | --- | --- | --- | -| June 30, 2021 | 21.2.3 | Only Oracle Portal 12.2.1.4 is supported and certified with the WebLogic Kubernetes operator version 3.1.1. +| June 10, 2022 | 22.2.3 | Only Oracle WebCenter Portal 12.2.1.4 is supported and certified with the WebLogic Kubernetes operator version 3.3.0. +| June 30, 2021 | 21.2.3 | Only Oracle WebCenter Portal 12.2.1.4 is supported and certified with the WebLogic Kubernetes operator version 3.1.1.

!hR=>~q()3D!}a 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 literal 0 HcmV?d00001 diff --git a/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-gp-add-datasource.png b/docs-source/content/wcportal-domains/manage-wcportal-domains/monitoring-and-publishing-logs/monitoring-domain/images/wme-gp-add-datasource.png new file mode 100644 index 0000000000000000000000000000000000000000..a39902e3892a320270510f9d137c27f60a077050 GIT binary patch literal 120555 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