7 Extending the WebLogic Server Deploy Tooling (WDT) Model

While the OSM cloud native toolkit provides a domain model that is sufficient to support the operation of the OSM application, there are a few aspects that you can customize to meet your business requirements. This chapter provides the general mechanism that OSM cloud native provides for how custom WebLogic Server Deploy Tooling (WDT) metadata can be used.

The following sections enable you to familiarize yourself with the basic extension mechanism. For details on using the sample scripts to add custom WDT metadata, see "Using the Sample Scripts to Extend the WDT Model".

About the Custom WDT Extension Mechanism

The OSM cloud native toolkit exposes an extension mechanism to extend the base WDT domain configuration. For better management practices, you must specify different WDT model fragments in multiple .tpl files that can be included in instances as necessary.

All extensions must be located in your source control repository in a directory referred to as customExtPath, which is provided during instance creation. This does not need to be the same location as specPath that contains the specification files. See the illustration about the directory structure in "Managing Configuration as Code".

Using the WDT Model Tools

This section describes the WDT model tools that you can use when extending the WDT model.

The WDT model tools are available at: https://github.com/oracle/weblogic-deploy-tooling. The documentation available on GitHub describes various tools, which are included in the OSM cloud native toolkit.

For a developer trying to modify or extend the WDT model for a custom OSM instance, the following tools are the most useful:
  • WDT Discover Domain
  • WDT Validate Model

WDT Discover Domain Tool

One way to generate the desired custom model is to manually create a WLS domain (using legacy installers, wlst scripts, console UI changes, and so on) that contains all the constructs that are required and is known to work, in terms of the custom use case. The WDT Discover Domain tool can be pointed at this WLS domain to generate a set of model files. These can be scanned and pruned to get the portions that are of custom interest. They can further be parameterized using WDT's properties files or using Helm values.

If WDT properties are used to parameterize, ensure that you add that properties file to the extension point in the custom implementation.

If Helm values are used to parameterize, ensure that you add these values to the appropriate location - project/instance/shape yamls.

To discover a domain, run the following commands on the prepared WLS admin server or standalone server:
# ensure ORACLE_HOME is properly set
cd $ORACLE_HOME
mkdir wdt && cd wdt
wget https://github.com/oracle/weblogic-deploy-tooling/releases/download/weblogic-deploy-tooling-1.6.0/weblogic-deploy.zip
# Replace 1.6.0 with the actual WDT version as per OSM documentation
unzip weblogic-deploy.zip
cd weblogic-deploy/bin
./discoverDomain.sh -oracle_home $ORACLE_HOME \
 -domain_home domain-home \
 -archive_file archive \
 -model_file model \
 -domain_type domain-type \
 -admin_user admin-user \
 -admin_url t3-admin-url
where:
  • archive and model are the directory+name of the files that the discovery tool creates. The model file is of primary importance in this situation.
  • domain-type is JRF for OSM applications

The command extracts the model from the running WLS instance. Alternatively, if it is sufficient to extract the model from the domain configuration files, the admin_user and admin_url parameters can be left out.

WDT Validate Model Tool

This tool is useful in the following scenarios:

  • When there is a need to see what attributes and sub-fields are available for a model element
  • When there is a need to see if a model fragment is valid

Trying to test a newly written or even a modified model file by incorporating it into an instance creation is cumbersome and often an inefficient way to test your changes. You need to check the Introspector logs to see the details of any errors.

With the Validate Model tool, it is easier to validate the model file, especially if you are building the model iteratively.

Common WDT Extension Mechanism

This section describes the extension mechanism that is generic and common to all methods of extending WDT metadata.

Enabling the Extension Mechanism

To enable the extension mechanism:
  1. Copy $OSM_CNTK/samples/_custom-domain-model.tpl to your source control repository customExtPath. This file is a single location where other template files, which store specific WDT metadata fragments, can be included for an OSM instance. This sets up the WDT fragments for re-use across a project, while allowing conditional inclusion based on instance level values in the specification files.
  2. Enable the extension mechanism by setting the custom flag to true in the project specification and including _custom-domain-model.tpl:
    custom:
      enabled: true
      #wdtFiles: {}
      wdtFiles:
       - _custom-domain-model.tpl
    The basic extension mechanism is now enabled.
For each WDT fragment that is destined for inclusion, perform the following additional steps:
  • Provide the WDT fragment
  • (Optional) Parameterize the WDT Fragment
  • Load the WDT Fragment
  • List the .tpl files
  • Debug the changes in the Helm chart

Providing the WDT Fragment

Naming convention dictates that the template files start with an underscore _. For example, _custom-extension-support.tpl.

You can copy any one of the WDT fragments provided in the samples, or you can create your own. If you provide your own WDT fragment, then you will need to reverse engineer the required metadata using the WDT tooling. For these samples, see "Using the WDT Model Tools".

If you create your own .tpl file, ensure that the WDT fragment is enclosed in a define block as follows:
{{- define "osm-domain.custom-extension-support" -}}
custom model fragment goes here
{{- end }}

(Optional) Parameterizing the WDT Fragment

Instead of hard coding the values into the WDT, you can parameterize the content so that specific values can be driven from the Helm chart. Determine which values fall into this category and then apply the following changes:

To parameterize the WDT fragment:

  1. Update the WDT to use a parameter as illustrated in the following example:
    Host: 'external.provider.hostname'
    
    becomes....
    
    Host: '{{ .Values.custom.extension.host }}'
  2. Add values to the application instance in either the project specification or the instance specification found in the source control at spec_Path.
    custom:
     enabled: true
     <extension>:
       host: provide_explicit_value_here

The custom area of the specification file is where you can add as much content as needed for your extension use cases. Oracle recommends that you keep the yaml structure as flat as possible.

Loading the WDT Fragment

The sample _custom-domain-model.tpl already has conditional inclusions for some of the samples provided in the toolkit. JMS, JDBC, and custom application archives can be enabled by providing the appropriate flag in the instance specification and including the specific .tpl file in the project specification. For the samples, you do this task as described in "Using the Sample Scripts to Extend the WDT Model".

Load the model fragment into extension_Directory/_custom-domain-model.tpl as follows:
{{- define "osm-domain.custom-domain-model" -}}
{{- $root := . }}
custom-<extension>-support.<index>.yaml: |+
 {{- include "osm-domain.custom-extension-support" $root | nindent 2 }}
{{- end }}

Note:

See the yaml naming convention that is specified by wdt - filename.yaml. The index used determines the loading order when there are multiple yaml files. Indexes below 70 are reserved for internal Oracle use.
The WDT may only need to be used conditionally. It is important to be able to exclude the fragment based on the values provided in the project specification. In this case, _custom-domain-model.tpl should include the condition that needs to be met for the WDT to be included.

Note:

Including the WDT in extension_Directory, which makes it available during instance creation, but not used does not pose any problems for Helm.
{{- define "osm-domain.custom-domain-model" -}}
{{- $root := . }}
{{- if .Values.custom.<extension>.enabled }}
custom-extension-support.index.yaml: |+
 {{- include "osm-domain.custom-extension-support" $root | nindent 2 }}
{{- end }}
{{- end }}

Listing the TPL Files in the Project

For each WDT fragment that is created in a .tpl file, it needs to be listed in the project specification.
custom:
  enabled: true
  #wdtFiles: {}
  wdtFiles:
   - _custom-domain-model.tpl
   - new_wdt.tpl

Debugging Helm Chart Changes

When making changes to existing yaml files or creating new WDT fragments, it is useful to test the changes before attempting to create an instance.

You can use the following scripts provided with the toolkit to debug Helm chart changes:

  • $OSM_CNTK/scripts/lint-osm-instance-chart.sh
  • $OSM_CNTK/scripts/create-instance-dry-run.sh

You can now create an OSM instance.

Using the Sample Scripts to Extend the WDT Model

This section provides instructions for extending the WDT model by using the sample scripts that are provided with the toolkit. You add custom WDT metadata to create your own OSM instances.

The general and common extension process described in "Common WDT Extension Mechanism" must be repeated for each of the use cases described in this section.

Adding a JDBC Datasource

The WDT fragment describing a JDBCSystemResource is provided in the $CNTK/samples/customExtension/_custom-jdbc-support.tpl sample file.

To incorporate this fragment into your OSM instance:
  1. Enable the extension mechanism by setting the custom flag to true and add the custom-domain-model to the list of included wdtFiles in the project specification:
    custom:
      enabled: true
      wdtFiles:
       - _custom-domain-model.tpl
  2. Provide the WDT fragment by copying $CNTK/samples/customExtensions/_custom-jdbc-support.tpl to the customExtPath in your source control repository.
  3. Parameterize the WDT fragment. The fragment has already been parameterized and uses values specified in the shape file. You must update the remaining values enclosed in angular brackets. By default, this WDT reads the JDBC values from the shape that is provided during instance creation.

    Note:

    Kubernetes Secrets can also be used to provide sensitive data such as username and password. See "Accessing Kubernetes Secrets from WDT Metadata" for details.
    resources:
     JDBCSystemResource:
     '<custom-conn-pool>':
     JdbcResource:
     JDBCDriverParams:
     URL: 'jdbc:oracle:thin:@<db-host>:<db-port>/<db-service>'
     PasswordEncrypted: '<password>'
     #PasswordEncrypted: '@@SECRET:my_secret_name:my_db_password@@'
     Properties:
     user:
     Value: '<user>'
     #Value: '@@SECRET:my_secret_name:my_db_user@@'
     oracle.net.CONNECT_TIMEOUT:
     Value: {{ default "10000" .Values.jdbc.oracleNetConnectTimeout }}
     oracle.jdbc.ReadTimeout:
     Value: {{ default "3660000" .Values.jdbc.oracleJdbcReadTimeout }}
     JDBCConnectionPoolParams:
     InitialCapacity: {{ default "0" .Values.jdbc.initialCapacity }}
     MaxCapacity: {{ default "15" .Values.jdbc.maxCapacity }}
     MinCapacity: {{ default "0" .Values.jdbc.minCapacity }}
     ShrinkFrequencySeconds: {{ default "900" .Values.jdbc.shrinkFrequencySeconds }}
     TestFrequencySeconds: {{ default "300" .Values.jdbc.testFrequencySeconds }}
     TestConnectionsOnReserve: {{ default "true" .Values.jdbc.testConnectionsOnReserve }}
     SecondsToTrustAnIdlePoolConnection: {{ default "10" .Values.jdbc.secondsToTrustAnIdlePoolConnection }}
     StatementCacheSize: {{ default "30" .Values.jdbc.statementCacheSize }}
     ConnectionCreationRetryFrequencySeconds: {{ default "30" .Values.jdbc.connectionCreationRetryFrequencySeconds }}
     IgnoreInUseConnectionsEnabled: {{ default "true" .Values.jdbc.ignoreInUseConnectionsEnabled }}
     InactiveConnectionTimeoutSeconds: {{ default "0" .Values.jdbc.inactiveConnectionTimeoutSeconds }}
     StatementCacheType: '{{ default "LRU" .Values.jdbc.statementCacheType }}'
     CountOfTestFailuresTillFlush: {{ default "5" .Values.jdbc.countOfTestFailuresTillFlush }}
     CountOfRefreshFailuresTillDisable: {{ default "5" .Values.jdbc.countOfRefreshFailuresTillDisable }}
     RemoveInfectedConnections: {{ default "false" .Values.jdbc.removeInfectedConnections }}
     ConnectionReserveTimeoutSeconds: {{ default "10" .Values.jdbc.connectionReserveTimeoutSeconds }}
     StatementTimeout: {{ default "3630" .Values.jdbc.statementTimeout }}
  4. The fragment is already configured for conditional loading based on the presence of the jdbc flag in the project specification. Set the jdbc flag to true.
    custom:
      enabled: true
      jdbc: true
  5. Add the JDBC .tpl file to the project specification:
    custom:
      enabled: true
      jdbc: true
      wdtFiles:
       - _custom-domain-model.tpl
       - _custom-jdbc-support.tpl
    You can now create the OSM instance.

Adding a JMS System Resource

The WDT fragment describing a JMS System Resource is provided in the $CNTK/samples/customExtension/_custom-jms-support.tpl sample file.

To incorporate this fragment into your OSM instance:
  1. Enable the extension mechanism by setting the custom flag to true and add the custom-domain-model to the list of included wdtFiles in the project specification:
    custom:
      enabled: true
      wdtFiles:
       - _custom-domain-model.tpl
  2. Provide the WDT fragment by copying $CNTK/samples/customExtensions/_custom-jms-support.tpl to the customExtPath in your source control repository. While this sample shows WDT for a JMS Queue and JMS Topic, any other JMS entity can be supplied instead. See "Using the WDT Model Tools" for details on establishing the correct WDT.
  3. Parameterize the WDT fragment. The fragment has not been parameterized. The text enclosed in angular brackets must be replaced with specific values.

    Alternatively, update the WDT to parameterize content and provide actual values in the project specification.

  4. The fragment is already configured for conditional loading based on the presence of the jms flag in the project specification. See the $CNTK/charts/osm/templates/_custom-domain-model.tpl template. Set the jms flag to true.
    custom:
      enabled: true
      jms: true
  5. Add the jms tpl file to the project specification:
    custom:
      enabled: true
      jms: true
      wdtFiles:
       - _custom-domain-model.tpl
       - _custom-jms-support.tpl
    You can now create the OSM instance.

Deploying Entities to an OSM WebLogic Domain

You can deploy any WebLogic Server deployable entity, such as an application EAR or WAR to an OSM WebLogic domain.

To deploy an entity to an OSM WebLogic Domain:

  1. Package the entity, for example, the application ear into an archive file and place it inside the container image used for creating OSM instances.

    Note:

    The WebLogic domain tooling expects application binaries to be available at the correct path within the archive. A script is provided for your convenience that packages the application into the correct path.
    cp application.ear samples/customExtensions
    cd samples/customExtensions
    ./make-custom-archive.sh archive_file_name.zip application.ear
  2. Build a new container image:
    cd samples/customExtensions
    docker build -t "image_name:tag" --build-arg base_image=osm_base_image --build-arg archive=archive_file_name.zip .
  3. Upload the generated image to your private Docker repository.
  4. Add the domain configuration.
    In addition to copying the archive file into the base image, you must supply custom configuration, which can be passed in by any one of following two mechanisms:
    • Inside the container image.

      This mechanism keeps the ear file together with the domain configuration in one location. This is best suited to applications that can be considered standard or fixed for all variants of a domain that are required (test, development, and production).

      Advantage: You do not need to add the custom domain configuration every time you create a domain.

      Disadvantage: If you want to change the configuration, it requires a change to the base image. In domains that are already up, an image change triggers a full restart of the domain.

      To add the domain configuration using this mechanism:

      1. Save your fragment in a YAML file that includes an index 70 or above. For example, custom-application-extension.70.yaml.
      2. Edit Dockerfile to copy the YAML file to the u01/wdt/models directory along with the archive.
    • Using the extension mechanism.

      This approach allows for per instance control over the application. This is best suited to situations where the application configuration needs to be dictated by the specific domain instance (for example, test vs. production).

      Advantage: Keeps all "variable" (per instance) configuration in one place at domain creation.

      Disadvantage: Domain creation for every instance that uses the application must remember to add the configuration.

      To use the extension mechanism:
      1. Enable the extension mechanism by setting the custom flag to true and add the custom-domain-model to the list of included wdtFiles in the project specification:
        custom:
          enabled: true
          wdtFiles:
           - _custom-domain-model.tpl
      2. Provide the WDT fragment by copying $CNTK/samples/customExtensions/_custom-application-support.tpl to the customExtPath in your source control repository.
      3. Parameterize the WDT fragment. The fragment has already been parameterized.
        appDeployments:
         Application:
         {{- .Values.custom.application_name }}:
         SourcePath: 'wlsdeploy/applications/{{- .Values.custom.binary_name }}.ear'
         ModuleType: ear
         StagingMode: nostage
         PlanStagingMode: nostage
         Target: '@@PROP:CLUSTER_NAME@@'
      4. Provide the values in the instance specification:
        custom:
          enabled: true
          application: true
          #additional values here
          application_name: myApplication
          binary_name: myApp
      5. Add the application flag and set it to true. The fragment is already configured for conditional loading based on the presence of the application flag in the project specification. See $CNTK/charts/osm/templates/_custom-domain-model.tpl in the toolkit.
        custom:
          enabled: true
          application: true
      6. Add the application tpl file to the project specification:
        custom:
          enabled: true
          application: true
          wdtFiles:
           - _custom-domain-model.tpl
           - _custom-application-support.tpl
    You can now create the OSM instance.

Extending the WDT Metadata for an External Authenticator

The OSM cloud native toolkit provides out-of-the-box configuration for a WebLogic domain using OpenLDAP as the authenticator. Using a different provider (even a different LDAP provider) requires different WDT metadata, which is a significant undertaking. The configuration required to support an alternate WLS provider would need to be investigated and developed independently using an existing WebLogic domain. Oracle's WDT Discover Domain Tool can analyze an existing domain and generate the corresponding WDT model. The WDT model fragment can then be used to configure the OSM domain using the toolkit extension mechanism.

See the following documentation for information on configuring a WebLogic domain with alternative authentication providers:

After the WDT is determined, it is provided during the creation process in the same way as other WDT metadata fragments. This section describes the process for setting up external authentication for OSM cloud native.

To set up external authentication:

  1. Disable OpenLDAP by editing the project specification in customExPath:
    authentication:
      openldap:
        enabled: false
  2. Copy $OSM_CNTK/samples/_custom-domain-model.tpl to your source control repository at customExtPath.
  3. Enable the extension mechanism by setting the custom flag to true in the project specification and including the _custom-domain-model.tpl
    custom:
      enabled: true
      wdtFiles:
       - _custom-domain-model.tpl
  4. Determine and provide the WDT model fragment for the security provider in the WebLogic domain. Once you know the WDT fragment that needs to be supplied, save it into a file in your source control repository at the customExtPath (_custom-provider-support.tpl).
    {{- define "osm.custom-provider-support" -}}
    topology:
     SecurityConfiguration:
     Realm:
     myrealm:
     AuthenticationProvider:
     '!DefaultAuthenticator':
     '!DefaultIdentityAsserter':
     YouLDAPProviderStartHere:
     .... <specific details here>
      
     DefaultAuthenticator:
     DefaultAuthenticator:
     ControlFlag: SUFFICIENT
     UseRetrievedUserNameAsPrincipal: true
     DefaultIdentityAsserter:
     DefaultIdentityAsserter:
    {{- end }}

    Note:

    You can review the fragment for an OpenLDAP provider that is included in the toolkit: $OSM_CNTK/charts/osm/templates/_osm-openldap-support.tpl
    The security configuration WDT should respect sensitive data by using secrets. See "Accessing Kubernetes Secrets from WDT Metadata" for details on how to access secret data from within your WDT fragment.
  5. (Optional) Update any parameters that should not be hard coded in the WDT fragment. Add these values to the project specification under the "custom" section.
  6. Load the model fragment by editing your custom_extension_path/ _custom-domain-model.tpl file:
    {{- define "osm.custom-domain-model" -}}
    {{- $root := . }}
    custom-provider-support.index.yaml: |+
      {{- include "osm.custom-provider-support" $root | nindent 2 }}
    {{- end }}
     
     
    ## If you would like conditional inclusion of the fragment...something like this instead
     
     
    {{- define "osm.custom-domain-model" -}}
    {{- $root := . }}
    {{- if .Values.custom.provider.flag}}
    custom-provider-support.index.yaml: |+
      {{- include "osm.custom-<provider>-support" $root | nindent 2 }}
    {{- end }}
    {{- end }}

    Note:

    Remember the yaml naming convention that is specified by wdt - filename.yaml. The index used determines the loading order when there are multiple yaml files. Indexes below 70 are reserved for internal Oracle use.
  7. Add the tpl file that has the authentication provider WDT into the project specification:
    custom:
      enabled: true
      wdtFiles:
       - _custom-domain-model.tpl
       - _custom-provider-support.tpl
    You can now create an OSM instance.

Accessing Kubernetes Secrets from WDT Metadata

The process of handling sensitive data inside a WDT fragment involves the following:

  • Creating Kubernetes secrets
  • Declaring the secrets in the specification file
  • Referencing the secrets from the WDT fragment

To access Kubernetes secrets from WDT metadata:

  1. Create the secret.

    Secrets must be created in the correct Kubernetes namespace. The namespace is already created when registering the namespace and aligns to your project name.

    To create the secret using the command line, run the following command:
    $kubectl -n project_Name create secret generic secret_Name \
     --from-literal=key1=$value \
     --from-literal=key2=$value
  2. Add the secret in the custom section of the instance specification in your source repository:
    # Custom secrets
    # replace the empty secret names with one or more secrets
    instance:
      customSecrets:
        enabled: true
        secretNames:
         - mysecret1
         - mysecret2
    Once you have created and declared your custom secrets, they can be referenced from elsewhere in the WDT model.
  3. Access the secret from inside a WDT fragment:
    Field1: '@@SECRET:secret_name:key1@@'
    Field2: '@@SECRET:secret_name:key2@@'

    where secret_name represents the secret name and key represents one of the keys in the secret.

Troubleshooting WDT Issues

This section provides details about some procedures that you may have to run in order to resolve issues with WDT.

Starting and Terminating a WDT Pod

The OSM image includes the WDT tools that are often needed to debug or discover a WDT fragment. You can start a temporary pod that provides access to these tools. Before starting the pod, download the container image of the OSM base image to ensure that the download time does not exceed the duration of the Kubernetes pod creation timeout.
kubectl run wdt --generator=run-pod/v1 \
 --image OSM_base_image -- sleep infinity
When the pod is no longer needed, you can delete it:
kubectl delete pod wdt

Validating a Model YAML File

To validate a model YAML file:

  1. Copy a model yaml into your temporary pod:
    kubectl cp model_file wdt:/tmp/model_file
  2. Run the following command and wait for the prompt:
    kubectl exec -ti wdt /bin/bash
  3. Validate the model file you copied:
    cd /u01/wdt/weblogic-deploy/bin
    ./validateModel.sh -oracle_home $ORACLE_HOME -model_file /tmp/model_file
  4. When you are done validating, exit the pod:
    exit

The line numbers returned by the validateModel script are exclusive of the comment lines. Either strip the comments first or do the calculation to get the "real" line number in the file.

This process can be iterated by first reviewing the WDT errors and warnings, fixing the YAML file, and then re-running the above procedure. Repeat this as required.

Note:

Model files can contain fragments of models, but each model element must have its full parentage, starting from section. For example, following is the sample if the fragment is the model element JmsResource:
resources:
 JMSSystemResource:
 JmsResource:
 model-fragment-to-validate

Displaying Valid Attributes and Child Attributes of a WDT Model

To display the attributes of a WDT model, run the following commands:

kubectl exec -ti wdt /bin/bash
# wait for prompt
cd /u01/wdt/weblogic-deploy/bin
./validateModel.sh -oracle_home $ORACLE_HOME \
 -print-usage path
exit

The path here is the WDT path to the model element of interest. For example, to see all the attributes and child attributes for SAFImportedDestinations, the path is resources:/JMSSystemResource/JmsResource/SAFImportedDestinations.

A common way to construct the path is to look for the element in a discovered model file and determine its yaml path. Another way is to start off with a path of section:, where section is one of "domainInfo", "topology", "resources" or "appDeployments". By iteratively discovering the child attributes, the final path can be built-up.

To shorten this search process, add the -recursive flag to the validateModel.sh script command line. Care should be taken as the output can be quite large at the higher levels.