Business Rules Engine
After Scaleup, mintpress_project executes the business rules engine to customise the configuration to match organisational rules. This is followed again by a dedupe_model call to bring down the declared resources to a minimum, again for readability and maintainability. The business rules are currently JSON files which define a list of rules to execute on the model - primarily around configurationList/resourceList items, since that is the heritage of the code, but also some mint model transformations as well. These rules are executed in order. The most common usage of this is via the mintpress_project chef resource.
(Also note that, if you are using chef, these are also available as chef resources - this is documented in the environmint-orchestration cookbook)
Sample Rules
[
{
"type": "StartupParameter",
"value": "-Xmx4096m",
"match": "-Xmx*",
"server": "AdminServer",
"enforce": "true"
},
{
"type": "StartupParameter",
"value": "-Dweblogic.Stdout=${logFilesLocationPath}/${/domains.name}/%Name%/%Name%.out",
"match": "-Dweblogic.Stdout=*",
"enforce": "true"
},
{
"type": "StartupParameter",
"value": "-Dweblogic.Stderr=${logFilesLocationPath}/${/domains.name}/%Name%/%Name%.err",
"match": "-Dweblogic.Stderr=*",
"enforce": "true"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"target": "wls.nodemanager.secure.listener",
"value": "true"
}
]
Note that you can have multiple business logic sets - specified also as an ordered list, and indeed it’s recommended that you do - for example, for the for one of our internal projects, we have an SSL ruleset, an Exalogic topology rule set, a Security rule set, and switchable singlesite/dualsite overrides.
Sample: singlesite-db.json
[
{
"type": "MintModel",
"tree": "site.databaseList",
"name": "jdbcUrl",
"value": "jdbc:oracle:thin:@(DESCRIPTION_LIST=(DESCRIPTION=(CONNECT_TIMEOUT=60)(RETRY_COUNT=3)(TRANSPORT_CONNECT_TIMEOUT=3)(FAILOVER=on)(LOAD_BALANCE=OFF)(ADDRESS_LIST=(LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=${ibscan})(PORT=1621)))(CONNECT_DATA=(SERVICE_NAME=${_.serviceName}))))"
}
]
Sample: dualsite-db.json
[
i {
"type": "MintModel",
"tree": "site.databaseList",
"name": "jdbcUrl",
"value": "jdbc:oracle:thin:@(DESCRIPTION_LIST=(DESCRIPTION=(CONNECT_TIMEOUT=60)(RETRY_COUNT=3)(TRANSPORT_CONNECT_TIMEOUT=3)(FAILOVER=on)(LOAD_BALANCE=OFF)(ADDRESS_LIST=(LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=${combinedEnvironmentName}xd-ibscan)(PORT=1621)))(ADDRESS_LIST=(LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=${siteBscan})(PORT=1621)))(CONNECT_DATA=(SERVICE_NAME=${_.serviceName}))))"
}
]
Structure
The structure of each entry in the list is
Field | Required? | Description | |
---|---|---|---|
type | Required | The type of rule which is being specified. Any rule which is not a known type is assumed to be a domain configuration type | |
value | Required | The value to set the attribute to | |
server | optional | Apply only to these managed servers. Is comma seperated, and takes unix glob format (soa, !AdminServern for example) | |
resourcename | optional | Forced name for the resource, if you want to create something specifically named. This will always create one and only one. Otherwise, the system will create a seperate resource for each managed server/cluster with ugly system-generated names | |
match | optional | Ignore this rule if the value already matches this string. Used, for example, to allow a user to override a default heap size by setting a match of ‘Xmx=*’ | |
enforce | optional | if set to “true”, this will force the attribute to be set to the value in this rule, including removing any other settings which match the “match” parameter. This is useful for enforcing security configuration even in the face of user override | |
namesuffix | optional | Create new resources with this suffix. Takes optional replacements of %CLUSTER% for cluster name, and %SERVER% for server name | |
propkey | optional | The property for specifying targetting - for when a configurationItem takes, for eample, serverName rather than targets. Using “Domain” indicates to the system that this is a domain wide configuration, and does not need to be targetted. | |
targettype | optional | For resources which can be targetted to a cluster or a server, takes ‘Cluster’ or ‘Server’ to specify which type. ‘Server’ is the default | |
extraprops | optional | Extra properties to add to the configurationList entry. This is a hash, and is ONLY effective on create - it will NOT update an existing resource at this time! |
In all cases, value also takes some parameter substitution - if you have a choice between these and runtime introspections for your task, you should use runtime introspections instead, however there are a variety of reasons why you may not wish to (for example, the configured value is changed at runtime, and you want to force the in-json-configured verison instead). In many cases, designtime introspections are more appropriate, however for multi-domain and multi-cluster topologies, these can be more complicated! However, we are considering deprecating at least some of these!
String | Replacement | Caveats | |
---|---|---|---|
%NODEMANAGER% | Name of our node manager | ||
%CLUSTERREPL% | Name of cluster replication channel | ||
%CLUSTERNAME% | Current weblogic domain name | Not recommended - use $/domain/domain.clusters/domain.clusters.name static introspection instead | |
%SERVERNAME% | Replication group of current cluster | Not recommended - use %Name% runtime introspection where supported | |
%DOMAINNAME% | Current weblogic domain name | Not recommended - use $/domains/domains.name static introspection instead | |
%CLUSTERREPLGROUP% | Replication group of current cluster | Not recommended - $/domains/domains.cluster/domains.cluster.replicationGroup | |
%LISTENNAME% | Listen address split at ‘-’ and ‘.’ in order to try and guess a short listen name | This will only work if your organisation names servers in a way that we splits like this. Consider using expressions instead if they do not. | |
%LISTENGROUP% | %LISTENNAME% with numbers removed. So turns soahost1 and soahost2 into soahost | ||
%DNSDOMAIN% | the listen address after the first . - hopefully, the DNS domain | This only works if you have FQDN in your listen address | |
%LISTENHOST% | Listen address of the current managed server | ||
%LISTENHOSTSHORT% | Listen address of the current managed server without the DNS domain | ||
%WKAxxx+999% | Generate coherence WKA for product xxx (osb, soa, oam, and odi are supported. ‘soa’ type will generate the generic tangosol.coherence.* parameters) parameters at listenPort+999 - see the coherence section below | Requires configuration - see the coherence section below | |
%ADMINLISTEN% | Listen address of the administration server of the current domain | Not recommended - use $/domains/domains.adminServer/domains.adminServer.listenAddress instead | |
%LISTEN+999% | Listen Port the current managed server offset 999 (so %LISTEN+1000% becomes 8002 if your listenAddressPort is 7002) | Recommended to use $() expressions instead - they are more flexable | |
%CERTNAME% | The name of the certificate for the current host | Requires configuration - see the SSL section below | |
%xxxHOST% | Hostname for the listen address on the xxx network, as defined in network configuration | Requires configuration - see the network topology section below |
Informing the system of your network topology
The “NETWORK” type is used to infrom the system about what your network looks like. It does not follow the standard patterns, but instead takes a sperateor and a postfix for how to create different network names from listen addresses.
[
{
"type": "NETWORK",
"class": "mgt",
"modifier": "m",
"seperator": "-"
},
{
"type": "NETWORK",
"class": "repl",
"modifier": "r",
"seperator": "-"
},
{
"type": "NETWORK",
"class": "ib",
"modifier": "p",
"seperator": "-"
}
]
field | description |
---|---|
class | what type of network we are defining - lookups with be %CLASSHOST%. in the above exmaples, %MGTHOST%, %REPLHOST%, and %IBHOST% |
seperator | Seperator for splitting network types. You can have emptystring, however it will ONLY work if your listen address is on an un-postfixed network in that case |
modifier | String to place after the seperator. the above configuration will generate host-m, host-r, and host-p respectivly. |
Updating MintModel properties
-
Tip: If you are using chef, you can instead use the mintpress_property resource for this - see the environmint-orchestration documentation!
The type “MintModel” can be used to update any attribute/property in the MintModel Tree, optionally as target or as name. You must specify one of tree (which can be ‘internalVariables’ if you’re planning to use internalvar), name, target, or internalvar
field | description |
---|---|
tree | Location in the tree. can use a ‘*’ to match ‘any item in this list. Also %NODEMANGER% for the name of your nodemaager, and %DOMAIN% for the name of your domain |
name | Name of property or attribute to set (i.e. listenAddress) |
target | Target of property or attribute to set (i.e. wls.nodemanager.setidentity) |
value | The value, with standard replacements as above |
internalvar | Internal Variable to set - this will override name/target/tree |
[
{
"type": "MintModel",
"internalvar": "adminAlias",
"tree": "internalVariables",
"value": "${environmentName}${site}${assetCode}"
},
{
"comment": "override this on soa servers...",
"type": "MintModel",
"internalvar": "adminAlias",
"tree": "internalVariables",
"value": "${environmentName}${assetCode}",
"server": "*soa*"
},
{
"comment": "Always set our admin server listen address to the admin alias defined as an internal variable",
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.domainList.%DOMAINNAME%.adminServer",
"name": "listenAddress",
"value": "${adminAlias}${dnsdomain}"
},
{
"comment": "override this on non-soa servers",
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"name": "listenAddress",
"value": "${_.host.basename}${ibPostfix}${dnsdomain}",
"server": "!*soa*"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"name": "listenAddress",
"value": "${_.host.basename}${repPostfix}${dnsdomain}",
"server": "*soa*"
}
]
SSL Certificate configuration
-
Tip: You can instead use the chef resource mintpress_ssl_configuration, for a much less verbose representation
SSL configuration relies on two custom types - KeyCertificate, and TrustCertificate. These cause the transfer list items to be created, which are always called %CERTNAME%Keystore and %CERTNAME%Truststore, (in DT format with certificate details stored in the transfer) and the passwords of those to be populated - current from either a textg file or the password vault.
{
"type": "KeyCertificate",
"value": "oi2${environmentName}${assetCode}-vip_keystore.jks:oi2${environmentName}${assetCode}-vip",
"certsource": "/environmint/binaries/certs/keystore",
"certpw": "file:/environmint/binaries/certs/cl4bc_${environmentName}.passwords",
"certpath": "${appFolder}/${assetCode}/environments/certs",
"server": "!AdminServer"
},
{
"type": "TrustCertificate",
"value": "oi2${environmentName}${assetCode}-vip_truststore.jks:oi2${environmentName}${assetCode}-vip",
"certsource": "/environmint/binaries/certs/keystore",
"certpw": "file:/environmint/binaries/certs/cl4bc_${environmentName}.passwords",
"certpath": "${appFolder}/${assetCode}/environments/certs",
"server": "!AdminServer"
},
Important points: * The value field is seperated by a colon into filename and key id * the certsource field specifies the source folder where the JKS files are stored * the certpath field specifies the destination folder to transfer the JKS files to * the certpw field specfies the location of the passwords. ‘file:/’ is a special type indicating a text file laid out as filename:password. databag:/ and other types taken by MintSecret will also work * The reason for server filtering, is that in the project this is taken from, AdminServers have special certificates - this allows us to specify that inside our configuration semantically
A complete domain SSL configuration is provided n the samples section - the mbean configuration should be quite familiar to anyone who has done this configuration manually.
Coherence
To have the rules engine generate your coherence startup paramters, you need to do two things: 1. Tell the system what your coherence listen addresses look like by using the Coherence LIsten parameter. This is a value as simple as “%LISTENNAME%” for the simple case. Note that this can NOT be an RT/DT introspection, bcause that would always resolve to ourselves, NOT to the other well known addresses! 2. Add a StartupParameter of %WKAtype+999% (where 999 is your coherence listen port from base) to add the parameter.
{
"type": "CoherenceListen",
"value": "%LISTENNAME%${repPostfix}${repDomain}"
},
{
"type": "StartupParameter",
"value": "%WKAsoa+4000%",
"server": "*soa*"
}
An equivalent chef configuration to this would be:
# We must configure our coherence first!
mintpress_resource "coherence-config" do
type "CoherenceListen"
value "%LISTENNAME%${repPostfix}${repDomain}"
end
# Startup parameter actually takes a list of parameters, but we only want one!
mintpress_startup_parameter "coherence-startup" do
asset "soa"
server "*soa*
parameters [ "%WKAsoa+4000%" ]
end
Running site code - adding executeList items
You can also add ExecuteItems from the rules engine, using the ExecuteItem type. It also takes a ‘when’ parameter, which matches one of the executeWhen states. It is currently limited to one and only one location
{
"type": "ExecuteItem",
"value": "/oracle/stage/apm/fixstartweblogic.sh ${/domains.locationPath} ${/domains.managedTopLocation}",
"when": "pre-online"
}
An equivalent chef resource, using the generic mintpress_resource resource, would be:
mintpress_resource "executeme" do
type "ExecuteItem"
value "/oracle/stage/apm/fixstartweblogic.sh ${/domains.locationPath} ${/domains.managedTopLocation}"
when "pre-online"
end
Transfering Files - adding transferList items
Similar to executeitem, there is also transferitem. The format of value is source:destination
{
"type": "TransferItem",
"value": "/oracle/stage/certs/common/adapters.jks:${/domains.locationPath}/config/fmwconfig/ovd/default/keystores/adapters.jks",
"when": "pre-online"
}
-
Tip: A dedicated chef resource for this will come in a later release
Samples
Configure SSL entirely
-
Tip: the mintpress_ssl_config resource does everything listed below!
[
{
"type": "KeyCertificate",
"value": "oi2${environmentName}${assetCode}-vip_keystore.jks:oi2${environmentName}${assetCode}-vip",
"certsource": "/environmint/binaries/certs/keystore",
"certpw": "file:/environmint/binaries/certs/cl4bc_${environmentName}.passwords",
"certpath": "${appFolder}/${assetCode}/environments/certs",
"server": "!AdminServer"
},
{
"type": "TrustCertificate",
"value": "oi2${environmentName}${assetCode}-vip_truststore.jks:oi2${environmentName}${assetCode}-vip",
"certsource": "/environmint/binaries/certs/keystore",
"certpw": "file:/environmint/binaries/certs/cl4bc_${environmentName}.passwords",
"certpath": "${appFolder}/${assetCode}/environments/certs",
"server": "!AdminServer"
},
{
"type": "KeyCertificate",
"value": "${adminAlias}-m_keystore.jks:${adminAlias}-m",
"certsource": "/environmint/binaries/certs/keystore",
"certpw": "file:/environmint/binaries/certs/cl4bc_${environmentName}.passwords",
"certpath": "${appFolder}/${assetCode}/environments/certs",
"server": "AdminServer"
},
{
"type": "TrustCertificate",
"value": "${adminAlias}-m_truststore.jks:${adminAlias}-m",
"certsource": "/environmint/binaries/certs/keystore",
"certpw": "file:/environmint/binaries/certs/cl4bc_${environmentName}.passwords",
"certpath": "${appFolder}/${assetCode}/environments/certs",
"server": "AdminServer"
},
{
"comment": "This section sets up the node manager"
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"name": "nmssl",
"target": "wls.nodemanager.secure.listener",
"value": "true"
},
{
"comment": "Why do we have both of these? /jj",
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"name": "type",
"value": "SSL"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"target": "wls.nodemanager.setidentity",
"value": "true"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"target": "wls.nodemanager.identitystorekey",
"value": "${/transferItems[%CERTNAME%Keystore].keyStorePassword}"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"target": "wls.nodemanager.identitypassphrase",
"value": "${/transferItems[%CERTNAME%Keystore].keyStorePassword}"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"target": "wls.nodemanager.identityname",
"value": "${/transferItems[%CERTNAME%Keystore].KeyAlias}"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"target": "wls.nodemanager.identitystorefile",
"value": "${/transferItems[%CERTNAME%Keystore].destinationFile}"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"target": "wls.nodemanager.truststorefile",
"value": "${/transferItems[%CERTNAME%Truststore].destinationFile}"
},
{
"type": "MintModel",
"tree": "site.environmentList.*.mwTopologyList.*.nodeManagerList.%NODEMANAGER%",
"target": "wls.nodemanager.truststorekey",
"value": "${/transferItems[%CERTNAME%Truststore].TruststorePassword}"
},
{
"comment": "This section sets up the managed server mbeans"
"type": "Server",
"propkey": "serverName",
"param": "SSL",
"key": "ServerPrivateKeyAlias",
"value": "${/transferItems[%CERTNAME%Keystore].KeyAlias}"
},
{
"type": "Server",
"propkey": "serverName",
"param": "SSL",
"key": "ServerPrivateKeyPassPhrase",
"value": "${/transferItems[%CERTNAME%Keystore].keyStorePassword}"
},
{
"type": "Server",
"propkey": "serverName",
"param": "SSL",
"key": "Enabled",
"value": "true"
},
{
"type": "Server",
"propkey": "serverName",
"key": "KeyStores",
"value": "CustomIdentityAndCustomTrust"
},
{
"type": "Server",
"propkey": "serverName",
"key": "CustomIdentityKeyStoreFileName",
"value": "${/transferItems[%CERTNAME%Keystore].destinationFile}"
},
{
"type": "Server",
"propkey": "serverName",
"key": "CustomIdentityKeyStorePassPhrase",
"value": "${/transferItems[%CERTNAME%Keystore].keyStorePassword}"
},
{
"type": "Server",
"propkey": "serverName",
"key": "CustomTrustKeyStorePassPhrase",
"value": "${/transferItems[%CERTNAME%Truststore].TruststorePassword}"
},
{
"type": "Server",
"propkey": "serverName",
"key": "CustomIdentityKeyStoreType",
"value": "jks"
},
{
"type": "Server",
"propkey": "serverName",
"key": "CustomTrustKeyStoreType",
"value": "jks"
},
{
"comment": "And finally, weblogic startup parameters!"
"type": "StartupParameter",
"value": "-Dweblogic.net.ssl.trustStore=${/transferItems[%CERTNAME%Truststore].destinationFile}",
"match": "-Dweblogic.net.ssl.trustStore=*",
"enforce": "true"
},
{
"type": "StartupParameter",
"value": "-Djavax.net.ssl.trustStore=${/transferItems[%CERTNAME%Truststore].destinationFile}",
"match": "-Djavax.net.ssl.trustStore=*",
"enforce": "true"
}
Configuring a third party APM agent (CA APM, in this case)
[
{
"type": "StartupClass",
"targettype": "Cluster",
"key": "ClassName",
"value": "com.wily.introscope.api.weblogic.IntroscopeStartupClass"
},
{
"type": "StartupClass",
"targettype": "Cluster",
"key": "LoadBeforeActivation",
"value": "true"
},
{
"type": "StartupClass",
"targettype": "Cluster",
"key": "LoadBeforeAppDeployment",
"value": "true"
},
{
"type": "StartupClass",
"targettype": "Cluster",
"key": "DeploymentOrder",
"value": "1000"
},
{
"type": "StartupClass",
"targettype": "Cluster",
"key": "FailureIsFatal",
"value": "false"
},
{
"type": "ExecuteItem",
"value": "/oracle/stage/apm/fixstartweblogic.sh ${/domains.locationPath} ${/domains.managedTopLocation}",
"when": "pre-online"
}
]