Setup WLS on AKS #9
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |