Skip to content

Setup WLS on AKS

Setup WLS on AKS #9

Workflow file for this run

name: Setup WLS on AKS
on:
workflow_dispatch:
inputs:
disambiguationSuffix:
description: "Included in names to disambiguate. Get from another pipeline execution"
default: "wls"
required: true
deleteResource:
description: "True to delete all the Azure resources after the deployments. False to keep Azure resources."
default: "true"
required: true
region:
description: "Azure region for resources"
required: true
default: westus
repository_dispatch:
schedule:
- cron: '0 0 13 * *' # run the workflow at the end of 21th monthly.
# All of the secrets in the env section are required. Run setup.sh to
# populate the git repository running this workflow with the necessary secrets.
env:
aksRepoUserName: ${{ secrets.AKS_REPO_USER_NAME }}
aksRepoBranchName: 2024-06-04-1-Q2
appInsightName: wlsakscargotracker${{ github.run_id }}
azCliVersion: 2.60.0
azureCredentials: ${{ secrets.AZURE_CREDENTIALS }}
dbAdminUser: weblogic
dbPassword: ${{ secrets.DB_PASSWORD }}
dbName: wlsdb${{ github.run_id }}${{ github.run_number }}
dbServerName: weblogicdbs
ocrSSOPSW: ${{ secrets.ORC_SSOPSW }}
ocrSSOUser: ${{ secrets.ORC_SSOUSER }}
refJavaee: d70ad03d3de9de45174b14d4077dbb2d148d5bbb
resourceGroupForDB: wlsd-db-${{ github.run_id }}-${{ github.run_number }}
resourceGroupForStorageAccount: wlsd-sa-${{ github.run_id }}-${{ github.run_number }}
storageAccountName: wlsdsa${{ github.run_id }}${{ github.run_number }}
storageContainerName: wlsdcon${{ github.run_id }}${{ github.run_number }}
wdtRuntimePassword: ${{ secrets.WDT_RUNTIMEPSW}}
wlsUserName: ${{ secrets.WLS_USERNAME }}
wlsPassword: ${{ secrets.WLS_PSW }}
jobs:
# Make it so the bicep file that causes WLS on AKS to be deployed is available to this workflow.
preflight:
outputs:
deleteResource: ${{steps.setup-env-variables.outputs.deleteResource}}
location: ${{ steps.setup-env-variables.outputs.location }}
resourceGroupForWlsAks: wlsd-aks-${{ steps.setup-env-variables.outputs.disambiguationSuffix }}-${{ github.run_number }}
runs-on: ubuntu-20.04
steps:
- name: Set up ENV variables
id: setup-env-variables
run: |
disambiguationSuffix=${{ github.event.inputs.disambiguationSuffix }}
if [ -z "${disambiguationSuffix}" ]; then
disambiguationSuffix=wls`date +%m%d`
fi
deleteResource=${{ github.event.inputs.deleteResource }}
if [ -z "${deleteResource}" ]; then
deleteResource='true'
fi
location=${{ github.event.inputs.region }}
if [[ -z "${location}" ]];then
location=westus
fi
echo "deleteResource: ${deleteResource}"
echo "disambiguationSuffix=${disambiguationSuffix}" >> $GITHUB_OUTPUT
echo "deleteResource=${deleteResource}" >> $GITHUB_OUTPUT
echo "location=${location}" >> $GITHUB_OUTPUT
# Set up database for use by application.
deploy-db:
needs: preflight
runs-on: ubuntu-latest
steps:
- name: Set variables
run: |
echo "location=${{ needs.preflight.outputs.location }}" >> $GITHUB_ENV
- uses: azure/login@v1
id: azure-login
with:
creds: ${{ env.azureCredentials }}
- name: Create Resource Group
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
echo "create resource group" ${{ env.resourceGroupForDB }}
az group create --verbose --name ${{ env.resourceGroupForDB }} --location ${location}
- name: Set Up Azure Postgresql to Test dbTemplate
id: setup-postgresql
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
echo "Deploy DB with name " ${{ env.dbName }}
az postgres flexible-server create \
--resource-group ${{ env.resourceGroupForDB }} \
--name ${{ env.dbName }} \
--location ${location} \
--admin-user ${{ env.dbAdminUser }} \
--admin-password ${{ env.dbPassword }} \
--version 16 \
--public-access 0.0.0.0 \
--tier Burstable \
--sku-name Standard_B1ms \
--yes
az postgres flexible-server db create \
--resource-group ${{ env.resourceGroupForDB }} \
--server-name ${{ env.dbName }} \
--database-name ${{ env.dbServerName }}
sleep 2m
echo "Allow Access To Azure Services"
az postgres flexible-server firewall-rule create \
-g ${{ env.resourceGroupForDB }} \
-n ${{ env.dbName }} \
-r "AllowAllWindowsAzureIps" \
--start-ip-address "0.0.0.0" \
--end-ip-address "0.0.0.0"
# Create an Azure storage account to hold the application war so that WLS on AKS can access it at deployment time.
deploy-storage-account:
needs: preflight
runs-on: ubuntu-latest
steps:
- name: Set variables
run: |
echo "location=${{ needs.preflight.outputs.location }}" >> $GITHUB_ENV
- name: Checkout cargotracker
uses: actions/checkout@v2
with:
path: cargotracker
- name: Maven build web app
run: |
mvn clean install -PweblogicOnAks --file cargotracker/pom.xml
- uses: azure/login@v1
id: azure-login
with:
creds: ${{ env.azureCredentials }}
- name: Create Resource Group
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
echo "create resource group" ${{ env.resourceGroupForStorageAccount }}
az group create --verbose --name ${{ env.resourceGroupForStorageAccount }} --location ${location}
- name: Create Storage Account
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
az storage account create --name ${{ env.storageAccountName }} \
--resource-group ${{ env.resourceGroupForStorageAccount }} \
--location ${location} \
--sku Standard_LRS \
--kind StorageV2
- name: Create Storage Container
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
az storage container create -n ${{ env.storageContainerName }} --account-name ${{ env.storageAccountName }}
- name: Upload built web app war file
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
az storage blob upload --account-name ${{ env.storageAccountName }} --container-name ${{ env.storageContainerName }} --file cargotracker/target/cargo-tracker.war --name cargo-tracker.war
# Invoke the bicep file, passing the necessary parameters to identify the database and war file.
deploy-wls-on-aks:
needs: [preflight, deploy-db,deploy-storage-account]
runs-on: ubuntu-latest
steps:
- name: Set variables
run: |
echo "resourceGroupForWlsAks=${{ needs.preflight.outputs.resourceGroupForWlsAks }}" >> $GITHUB_ENV
echo "location=${{ needs.preflight.outputs.location }}" >> $GITHUB_ENV
- uses: azure/login@v1
id: azure-login
with:
creds: ${{ env.azureCredentials }}
- name: Query web app blob url and set to env
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
sasTokenValidTime=3600
expiryData=$(( `date +%s`+${sasTokenValidTime}))
sasTokenEnd=`date -d@"$expiryData" -u '+%Y-%m-%dT%H:%MZ'`
sasToken=$(az storage account generate-sas \
--permissions r \
--account-name ${{ env.storageAccountName }} \
--services b \
--resource-types sco \
--expiry $sasTokenEnd -o tsv)
cargoTrackerBlobUrl=$(az storage blob url --container-name ${{ env.storageContainerName }} \
--name cargo-tracker.war \
--account-name ${{ env.storageAccountName }} \
--sas-token ${sasToken} -o tsv)
echo "cargoTrackerBlobUrl=${cargoTrackerBlobUrl}" >> $GITHUB_ENV
- name: Create Resource Group
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
echo "create resource group" ${resourceGroupForWlsAks}
az group create --verbose --name ${resourceGroupForWlsAks} --location ${location}
- name: Checkout cargotracker
uses: actions/checkout@v2
with:
path: cargotracker
- name: Prepare parameter file
run: |
echo "https://raw.githubusercontent.com/${aksRepoUserName}/weblogic-azure/${aksRepoBranchName}/weblogic-azure-aks/src/main/arm/mainTemplate.json"
echo "replace placeholders using real parameter"
bash cargotracker/src/test/aks/genParameters.sh \
${aksRepoUserName} \
${aksRepoBranchName} \
${cargoTrackerBlobUrl} \
${dbPassword} \
${dbAdminUser} \
"jdbc:postgresql://${dbName}.postgres.database.azure.com:5432/postgres" \
${location} \
${ocrSSOPSW} \
${ocrSSOUser} \
${wdtRuntimePassword} \
${wlsPassword} \
${wlsUserName} \
cargotracker/src/test/aks/parameters.json
ls cargotracker/src/test/aks
# Validate the parameters file in the context of the bicep template to be invoked. This will catch some errors before taking the time to start the full deployment.
- name: Validate Deploy of WebLogic Server Cluster Domain offer
id: validate-wls-cluster-deployment
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
az deployment group validate \
--debug \
--resource-group ${resourceGroupForWlsAks} \
--name wls-on-aks \
--parameters @cargotracker/src/test/aks/parameters.json \
--template-uri https://raw.githubusercontent.com/${aksRepoUserName}/weblogic-azure/${aksRepoBranchName}/weblogic-azure-aks/src/main/arm/mainTemplate.json
# Invoke the bicep template with the parameters file.
- name: Deploy WebLogic Server Cluster Domain offer
id: deploy-wls-cluster
uses: azure/CLI@v1
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
az deployment group create \
--verbose \
--resource-group ${resourceGroupForWlsAks} \
--name wls-on-aks \
--parameters @cargotracker/src/test/aks/parameters.json \
--template-uri https://raw.githubusercontent.com/${aksRepoUserName}/weblogic-azure/${aksRepoBranchName}/weblogic-azure-aks/src/main/arm/mainTemplate.json
# Connect to AKS cluster for JMS configuration.
- name: Connect to AKS cluster
run: |
echo "connect to cluster"
aksClusterName=$(az resource list --resource-group ${resourceGroupForWlsAks} --query "[?type=='Microsoft.ContainerService/managedClusters'].name|[0]" -o tsv)
az aks get-credentials --resource-group ${resourceGroupForWlsAks} --name $aksClusterName
# Apply JMS configuration in src/test/aks/cargo-tracker-jms.yaml to configmap. This is necessary to have Cargo Tracker fully operational.
- name: Generate&Apply configmap
run: |
wlsConfigmapName="sample-domain1-wdt-config-map"
# Get the content of JMS configuration from src/test/aks/cargo-tracker-jms.yaml.
configmapJMSData=$(kubectl create configmap ${wlsConfigmapName} -n sample-domain1-ns \
--from-file=cargotracker/src/test/aks/cargo-tracker-jms.yaml \
--dry-run=client \
-o jsonpath='{.data}')
# Patch JMS configuration to configmap sample-domain1-wdt-config-map.
kubectl patch configmap ${wlsConfigmapName} -n sample-domain1-ns \
--type merge -p '{"data":'"$configmapJMSData"'}'
- name: Provision Application Insights
run: |
az extension add --upgrade -n application-insights
workspaceId=$(az resource list \
--resource-group ${resourceGroupForWlsAks} \
--query "[?type=='Microsoft.OperationalInsights/workspaces'].name|[0]" \
-o tsv)
az monitor app-insights component create \
--app ${{ env.appInsightName }} \
--location ${location} \
--resource-group ${resourceGroupForWlsAks} \
--workspace ${workspaceId}
- name: Connect to App Insights
run: |
appInsightConnectionString=$(az monitor app-insights component show \
--resource-group ${resourceGroupForWlsAks} \
--query '[0].connectionString' -o tsv)
curl -m 120 --retry 5 -LO https://github.com/microsoft/ApplicationInsights-Java/releases/download/3.4.10/applicationinsights-agent-3.4.10.jar
kubectl exec -n sample-domain1-ns -it sample-domain1-admin-server -- /bin/bash -c "mkdir /shared/libs"
kubectl cp -n sample-domain1-ns applicationinsights-agent-3.4.10.jar sample-domain1-admin-server:/shared/libs/applicationinsights-agent-3.4.10.jar
wlsNamespace=sample-domain1-ns
wlsDomainId=sample-domain1
agentPath="-javaagent:/shared/libs/applicationinsights-agent-3.4.10.jar"
javaOptions=$(kubectl -n ${wlsNamespace} get domain ${wlsDomainId} -o json | jq '. | .spec.serverPod.env | .[] | select(.name=="JAVA_OPTIONS") | .value' | tr -d "\"")
javaOptions="${agentPath} ${javaOptions}"
javaOptionsIndex=$(kubectl -n ${wlsNamespace} get domain ${wlsDomainId} -o json | jq '.spec.serverPod.env | map(.name == "JAVA_OPTIONS") | index(true)')
cat <<EOF >patch-file.json
[
{
"op": "remove",
"path": "/spec/serverPod/env/${javaOptionsIndex}"
},
{
"op": "add",
"path": "/spec/serverPod/env/-",
"value": {
"name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
"value": "${appInsightConnectionString}"
}
},
{
"op": "add",
"path": "/spec/serverPod/env/-",
"value": {
"name": "JAVA_OPTIONS",
"value": "${javaOptions}"
}
}
]
EOF
kubectl -n ${wlsNamespace} patch domain ${wlsDomainId} \
--type=json \
--patch-file patch-file.json
- name: Cause a rolling update on the cluster
run: |
restartVersion=$(kubectl -n sample-domain1-ns get domain sample-domain1 '-o=jsonpath={.spec.restartVersion}')
# increase restart version
restartVersion=$((restartVersion + 1))
# record timestamp before apply changes
timestampBeforePatchingDomain=$(date +%s)
# get the replica number
replicas=$(kubectl -n sample-domain1-ns get domain sample-domain1 -o json | jq '. | .spec.clusters[] | .replicas')
kubectl -n sample-domain1-ns patch domain sample-domain1 \
--type=json \
'-p=[{"op": "replace", "path": "/spec/restartVersion", "value": "'${restartVersion}'"}]'
echo "timestampBeforePatchingDomain=${timestampBeforePatchingDomain}" >> $GITHUB_ENV
echo "replicas=${replicas}" >> $GITHUB_ENV
# Make sure all the pods are running.
- name: Verify pods are restarted
run: |
# interval of checking pod status.
checkPodStatusInterval=20
# max attempt to check pod status.
checkPodStatusMaxAttemps=30
# domain and namespaces
wlsDomainUID="sample-domain1"
wlsDomainNS=${wlsDomainUID}-ns
updatedPodNum=0
attempt=0
echo $timestampBeforePatchingDomain $replicas $wlsDomainUID $checkPodStatusMaxAttemps $checkPodStatusInterval
while [[ ${updatedPodNum} -le ${replicas} ]] && [[ $attempt -le ${checkPodStatusMaxAttemps} ]]; do
echo "attempts ${attempt}"
ret=$(kubectl get pods -n ${wlsDomainNS} -l weblogic.domainUID=${wlsDomainUID} -o json | jq '.items[] | .metadata.creationTimestamp' | tr -d "\"")
counter=0
for item in $ret; do
podCreateTimeStamp=$(date -u -d "${item}" +"%s")
echo "pod create time: $podCreateTimeStamp, base time: ${timestampBeforePatchingDomain}"
if [[ ${podCreateTimeStamp} -gt ${timestampBeforePatchingDomain} ]]; then
counter=$((counter + 1))
fi
done
updatedPodNum=$counter
echo "Number of new pod: ${updatedPodNum}"
attempt=$((attempt + 1))
sleep ${checkPodStatusInterval}
done
if [[ ${attempt} -gt ${checkPodStatusMaxAttemps} ]]; then
echo "Failed to restart all weblogic server pods. "
exit 1
fi
- name: Make REST API calls
run: |
gatewayPublicIPId=$(az network application-gateway list \
--resource-group ${resourceGroupForWlsAks} \
--query '[0].frontendIPConfigurations[0].publicIPAddress.id' -o tsv)
gatewayUrl=$(az network public-ip show --ids ${gatewayPublicIPId} --query 'dnsSettings.fqdn' -o tsv)
cargoUrl="http://${gatewayUrl}/cargo-tracker/"
# get request
curl -X GET -H "Accept: application/json" "${cargoUrl}rest/graph-traversal/shortest-path?origin=CNHKG&destination=USNYC"
# post request
currentDateTime=$(date +'%m/%d/%Y %I:%M %p')
cat <<EOF >data.json
{
"completionTime": "${currentDateTime}",
"trackingId": "ABC123",
"eventType": "UNLOAD",
"unLocode": "USNYC",
"voyageNumber": "0200T"
}
EOF
curl -X POST -d "@data.json" -H "Content-Type: application/json" ${cargoUrl}rest/handling/reports
# EJB failure
currentDateTime=$(date +'%m/%d/%Y %H:%M:%S')
cat <<EOF >data.json
{
"completionTime": "${currentDateTime}",
"trackingId": "ABC123",
"eventType": "UNLOAD",
"unLocode": "USNYC",
"voyageNumber": "0200T"
}
EOF
curl -X POST -d "@data.json" -H "Content-Type: application/json" ${cargoUrl}rest/handling/reports
cleanup:
if: always()
needs: [preflight, deploy-db,deploy-storage-account, deploy-wls-on-aks]
runs-on: ubuntu-latest
steps:
- uses: azure/login@v1
id: azure-login
with:
creds: ${{ env.azureCredentials }}
- name: Delete Azure resources.
uses: azure/CLI@v1
if: ${{ needs.preflight.outputs.deleteResource == 'true' }}
with:
azcliversion: ${{ env.azCliVersion }}
inlineScript: |
echo "delete... " ${{ env.resourceGroupForStorageAccount }}
az group delete --yes --no-wait --verbose --name ${{ env.resourceGroupForStorageAccount }}
echo "delete... " ${{ needs.preflight.outputs.resourceGroupForWlsAks }}
az group delete --yes --no-wait --verbose --name ${{ needs.preflight.outputs.resourceGroupForWlsAks }}
echo "delete... " ${{ env.resourceGroupForDB }}
az group delete --yes --no-wait --verbose --name ${{ env.resourceGroupForDB }}
alert:
needs: [deploy-db,deploy-storage-account, deploy-wls-on-aks, cleanup]
if: failure()
runs-on: ubuntu-latest
steps:
- name: Send Teams message
if: ${{ github.repository_owner == 'azure-javaee' }}
run: |
echo "Job failed, send notification to Teams"
# https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=dotnet
curl ${{ secrets.MSTEAMS_WEBHOOK }} \
-H 'Content-Type: application/json' \
--data-binary @- << EOF
{
"@context":"http://schema.org/extensions",
"@type":"MessageCard",
"text":"Workflow failed in cargotracker-wls-aks repository, please take a look at: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${{ github.run_id }}"
}
EOF