diff --git a/.github/actions/database-parameters/action.yaml b/.github/actions/database-parameters/action.yaml new file mode 100644 index 000000000..53af62005 --- /dev/null +++ b/.github/actions/database-parameters/action.yaml @@ -0,0 +1,143 @@ +name: Get Database parameters +description: Get Database parameters + +inputs: + databaseType: + description: "databaseType" + required: true + uamiId: + description: "uamiId" + required: true + serverHost: + description: "serverHost" + required: true + dbInstanceName: + description: "dbInstanceName" + required: true + dbAdminUser: + description: "dbAdminUser" + required: false + default: "testuser" + databaseName: + description: "databaseName" + required: true + default: "testdb" + +outputs: + enableDB: + description: "enableDB" + value: ${{ steps.database-parameters.outputs.enableDB }} + enablePswlessConnection: + description: "enablePswlessConnection" + value: ${{ steps.database-parameters.outputs.enablePswlessConnection }} + databaseType: + description: "databaseType" + value: ${{ steps.database-parameters.outputs.databaseType }} + dsConnectionURL: + description: "dsConnectionURL" + value: ${{ steps.database-parameters.outputs.dsConnectionURL }} + dbUser: + description: "dbUser" + value: ${{ steps.database-parameters.outputs.dbUser }} + dbIdentity: + description: "dbIdentity" + value: ${{ steps.database-parameters.outputs.dbIdentity }} + +runs: + using: "composite" + steps: + - name: Set up environment variables + shell: bash + id: database-parameters + run: | + enableDB=false + databaseType=sqlserver + dsConnectionURL=jdbc:postgresql://contoso.postgres.database:5432/${{ inputs.databaseName }} + dbUser=contosoDbUser + enablePswlessConnection=false + dbIdentity={} + serverHost=${{ inputs.serverHost }} + uamiId=${{ inputs.uamiId }} + echo "databaseType: ${{ inputs.databaseType }}" + echo "serverHost : $serverHost" + if ${{ inputs.databaseType == 'mssqlserver' }}; then + echo "Using mssqlserver database type" + enableDB=true + databaseType=sqlserver + dsConnectionURL="jdbc:sqlserver://$serverHost:1433;database=${{ inputs.databaseName }}" + dbUser=${{ inputs.dbAdminUser }}@${{ inputs.dbInstanceName }} + elif ${{ inputs.databaseType == 'mssqlserver-passwordless' }}; then + echo "Using mssqlserver-passwordless database type" + enableDB=true + enablePswlessConnection=true + databaseType=sqlserver + dsConnectionURL="jdbc:sqlserver://$serverHost:1433;database=${{ inputs.databaseName }}" + dbUser=${{ inputs.dbAdminUser }}@${{ inputs.dbInstanceName }} + dbIdentity=$(jq -n \ + --arg uamiId "$uamiId" \ + '{ + "type": "UserAssigned", + "userAssignedIdentities": { + ($uamiId): {} + } + }'| jq -c '.') + elif ${{ inputs.databaseType == 'oracle' }}; then + echo "Using oracle database type" + enableDB=true + databaseType=oracle + dsConnectionURL=jdbc:oracle:thin:@${serverHost}:1521/oratest1 + dbUser=${{ inputs.dbAdminUser }} + elif ${{ inputs.databaseType == 'mysql(flexible)' }}; then + echo "Using mysql(flexible) database type" + enableDB=true + databaseType=mysql + dsConnectionURL=jdbc:mysql://$serverHost:3306/${{ inputs.databaseName }}?sslMode=REQUIRED + dbUser=${{ inputs.dbAdminUser }} + elif ${{ inputs.databaseType == 'mysql-passwordless(flexible)' }}; then + echo "Using mysql-passwordless(flexible) database type" + enableDB=true + enablePswlessConnection=true + dbUser=$(basename "$uamiId") + dbIdentity=$(jq -n \ + --arg uamiId "$uamiId" \ + '{ + "type": "UserAssigned", + "userAssignedIdentities": { + ($uamiId): {} + } + }'| jq -c '.' ) + databaseType=mysql + dsConnectionURL=jdbc:mysql://$serverHost:3306/${{ inputs.databaseName }} + elif ${{ inputs.databaseType == 'postgresql(flexible)' }}; then + echo "Using postgresql(flexible) database type" + enableDB=true + databaseType=postgresql + dsConnectionURL="jdbc:postgresql://$serverHost:5432/${{ inputs.databaseName }}" + dbUser=${{ inputs.dbAdminUser }} + elif ${{ inputs.databaseType == 'postgresql-passwordless(flexible)' }}; then + echo "Using postgresql-passwordless(flexible) database type" + enableDB=true + enablePswlessConnection=true + dbUser=$(basename "$uamiId") + dbIdentity=$(jq -n \ + --arg uamiId "$uamiId" \ + '{ + "type": "UserAssigned", + "userAssignedIdentities": { + ($uamiId): {} + } + }'| jq -c '.') + databaseType=postgresql + dsConnectionURL="jdbc:postgresql://$serverHost:5432/${{ inputs.databaseName }}" + fi + + echo "enableDB=$enableDB" >> "$GITHUB_OUTPUT" + echo "enablePswlessConnection=$enablePswlessConnection" >> "$GITHUB_OUTPUT" + echo "databaseType=$databaseType" >> "$GITHUB_OUTPUT" + echo "dsConnectionURL=$dsConnectionURL" >> "$GITHUB_OUTPUT" + echo "dbUser=$dbUser" >> "$GITHUB_OUTPUT" + echo "dbIdentity=$dbIdentity" >> "$GITHUB_OUTPUT" + echo "dsConnectionURL=$dsConnectionURL" + echo "dbUser=$dbUser" + echo "Database parameters set successfully" + diff --git a/.github/actions/database-provision/action.yaml b/.github/actions/database-provision/action.yaml new file mode 100644 index 000000000..582908a84 --- /dev/null +++ b/.github/actions/database-provision/action.yaml @@ -0,0 +1,287 @@ +name: Database provision +description: Database provision + +inputs: + databaseType: + description: "databaseType" + required: true + resourceGroup: + description: "resourceGroup" + required: true + uamiName: + description: "uamiName" + required: true + location: + description: "location" + required: true + dbInstanceName: + description: "dbInstanceName" + required: true + dbPassword: + description: "dbPassword" + required: true + dbAdminUser: + description: "dbAdminUser" + required: false + default: "testuser" + databaseName: + description: "databaseName" + required: true + default: "testdb" + +outputs: + serverHost: + description: "serverHost" + value: ${{ steps.resource_outputs.outputs.serverHost }} + uamiId: + description: "uamiId" + value: ${{ steps.resource_outputs.outputs.uamiId }} + +runs: + using: "composite" + steps: + # 01-Deploy an instance of Azure SQL Database + - name: Echo inputs + shell: bash + run: | + echo "resourceGroup=${{ inputs.resourceGroup }}" + echo "uamiName=${{ inputs.uamiName }}" + echo "location=${{ inputs.location }}" + echo "dbInstanceName=${{ inputs.dbInstanceName }}" + echo "dbAdminUser=${{ inputs.dbAdminUser }}" + echo "databaseName=${{ inputs.databaseName }}" + - name: Deploy an instance of Azure SQL Database + id: deploy-mssqlserver + if: ${{ inputs.databaseType == 'mssqlserver' }} + shell: bash + run: | + az sql server create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --admin-user ${{ inputs.dbAdminUser }} --admin-password ${{ inputs.dbPassword }} \ + --location ${{ inputs.location }} + host=$(az sql server show \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --query "fullyQualifiedDomainName" -o tsv) + # Allow Azure services to access + az sql server firewall-rule create \ + --resource-group ${{ inputs.resourceGroup }} \ + --server ${{ inputs.dbInstanceName }} \ + --name "AllowAllAzureIps" --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0 + az sql db create --resource-group ${{ inputs.resourceGroup }} \ + --server ${{ inputs.dbInstanceName }} \ + --name ${{ inputs.databaseName }} + + echo "serverHost=${host}" >> "$GITHUB_ENV" + + - name: Deploy an instance of Azure SQL passwordless Database + id: deploy-mssqlserver-passwordless + if: ${{ inputs.databaseType == 'mssqlserver-passwordless' }} + shell: bash + run: | + # Create a user-assigned managed identity + az identity create --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} + # Export the resource ID of the user-assigned managed identity as an environment variable + uamiId=$(az identity show --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} --query id -o tsv) + objectId=$(az identity show --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} --query principalId -o tsv) + + az sql server create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --admin-user ${{ inputs.dbAdminUser }} \ + --admin-password ${{ inputs.dbPassword }} \ + --assign-identity \ + --external-admin-principal-type Application \ + --external-admin-name ${{ inputs.uamiName }} \ + --external-admin-sid $objectId \ + --location ${{ inputs.location }} + host=$(az sql server show \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --query "fullyQualifiedDomainName" -o tsv) + # Allow Azure services to access + az sql server firewall-rule create \ + --resource-group ${{ inputs.resourceGroup }} \ + --server ${{ inputs.dbInstanceName }} \ + --name "AllowAllAzureIps" --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0 + az sql db create --resource-group ${{ inputs.resourceGroup }} \ + --server ${{ inputs.dbInstanceName }} \ + --name ${{ inputs.databaseName }} + + echo "serverHost=${host}" >> "$GITHUB_ENV" + echo "uamiId=${uamiId}" >> "$GITHUB_ENV" + + - name: Deploy an instance of Azure Database for MySQL + id: deploy-mysql + if: ${{ inputs.databaseType == 'mysql(flexible)' }} + shell: bash + run: | + az mysql flexible-server create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --admin-user myadmin \ + --admin-password ${{ inputs.dbPassword }} \ + --sku-name Standard_B1ms \ + --location ${{ inputs.location }} \ + --version 8.0.21 \ + --yes + + # Allow Azure services to access + az mysql flexible-server firewall-rule create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --rule-name "AllowAllAzureIps" \ + --start-ip-address 0.0.0.0 \ + --end-ip-address 0.0.0.0 + # Allow current IP to access MySQL server + currentIp=$(curl -s https://icanhazip.com) + az mysql flexible-server firewall-rule create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --rule-name "AllowCurrentIp" \ + --start-ip-address ${currentIp} \ + --end-ip-address ${currentIp} + host=$(az mysql flexible-server show \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --query "fullyQualifiedDomainName" -o tsv) + + wget --no-check-certificate https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem + mysql -h $host -u myadmin -p${{ inputs.dbPassword }} --ssl-ca=DigiCertGlobalRootCA.crt.pem << EOF + CREATE DATABASE ${{ inputs.databaseName }}; + CREATE USER '${{ inputs.dbAdminUser }}'@'%' IDENTIFIED BY '${{ inputs.dbPassword }}'; + GRANT ALL PRIVILEGES ON ${{ inputs.databaseName }} . * TO '${{ inputs.dbAdminUser }}'@'%'; + FLUSH PRIVILEGES; + EOF + + echo "serverHost=${host}" >> "$GITHUB_ENV" + + - name: Deploy an instance of Azure Database for MySQL passwordless + id: deploy-mysql-passwordless + if: ${{ inputs.databaseType == 'mysql-passwordless(flexible)' }} + shell: bash + run: | + az mysql flexible-server create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --admin-user myadmin \ + --admin-password ${{ inputs.dbPassword }} \ + --sku-name Standard_B1ms \ + --location ${{ inputs.location }} \ + --version 8.0.21 \ + --yes + + # Allow Azure services to access + az mysql flexible-server firewall-rule create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --rule-name "AllowAllAzureIps" \ + --start-ip-address 0.0.0.0 \ + --end-ip-address 0.0.0.0 + # Allow current IP to access MySQL server + currentIp=$(curl -s https://icanhazip.com) + az mysql flexible-server firewall-rule create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --rule-name "AllowCurrentIp" \ + --start-ip-address ${currentIp} \ + --end-ip-address ${currentIp} + host=$(az mysql flexible-server show \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --query "fullyQualifiedDomainName" -o tsv) + + wget --no-check-certificate https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem + mysql -h $host -u myadmin -p${{ inputs.dbPassword }} --ssl-ca=DigiCertGlobalRootCA.crt.pem << EOF + CREATE DATABASE ${{ inputs.databaseName }}; + CREATE USER '${{ inputs.dbAdminUser }}'@'%' IDENTIFIED BY '${{ inputs.dbPassword }}'; + GRANT ALL PRIVILEGES ON ${{ inputs.databaseName }} . * TO '${{ inputs.dbAdminUser }}'@'%'; + FLUSH PRIVILEGES; + EOF + + # Create a user-assigned managed identity + az identity create --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} + # Export the resource ID of the user-assigned managed identity as an environment variable + uamiId=$(az identity show --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} --query id -o tsv) + objectId=$(az identity show --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} --query principalId -o tsv) + + az mysql flexible-server ad-admin create \ + --resource-group ${{ inputs.resourceGroup }} \ + --server-name ${{ inputs.dbInstanceName }} \ + --display-name ${{ inputs.uamiName }} \ + --object-id $objectId \ + --identity $uamiId + + echo "serverHost=${host}" >> "$GITHUB_ENV" + echo "uamiId=${uamiId}" >> "$GITHUB_ENV" + + - name: Deploy an instance of Azure Database for PostgreSQL + id: deploy-postgresql + if: ${{ inputs.databaseType == 'postgresql(flexible)' }} + shell: bash + run: | + az postgres flexible-server create \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --admin-user ${{ inputs.dbAdminUser }} --admin-password ${{ inputs.dbPassword }} \ + --public-access 0.0.0.0 \ + --location ${{ inputs.location }} \ + --yes + echo "Get the host name of the PostgreSQL server" + host=$(az postgres flexible-server show \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --query "fullyQualifiedDomainName" -o tsv) + echo "Create a database in the PostgreSQL server" + az postgres flexible-server db create --resource-group ${{ inputs.resourceGroup }} \ + --server-name ${{ inputs.dbInstanceName }} \ + --database-name ${{ inputs.databaseName }} + + echo "serverHost=${host}" >> "$GITHUB_ENV" + - name: Deploy an instance of Azure Database for PostgreSQL passwordless + if: ${{ inputs.databaseType == 'postgresql-passwordless(flexible)' }} + id: deploy-postgresql-passwordless + shell: bash + run: | + + # Create a user-assigned managed identity + az identity create --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} + # Export the resource ID of the user-assigned managed identity as an environment variable + uamiId=$(az identity show --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} --query id -o tsv) + objectId=$(az identity show --name ${{ inputs.uamiName }} --resource-group ${{ inputs.resourceGroup }} --query principalId -o tsv) + + az postgres flexible-server create \ + --microsoft-entra-auth Enabled \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --public-access 0.0.0.0 \ + --location ${{ inputs.location }} \ + --yes + echo "Set the user-assigned managed identity as the Microsoft Entra admin for the PostgreSQL server" + sleep 120 # Wait for the server to be ready + az postgres flexible-server microsoft-entra-admin create \ + --resource-group ${{ inputs.resourceGroup }} \ + --server-name ${{ inputs.dbInstanceName }} \ + --display-name ${{ inputs.uamiName }} \ + --object-id $objectId \ + --type ServicePrincipal + echo "Get the host name of the PostgreSQL server" + host=$(az postgres flexible-server show \ + --resource-group ${{ inputs.resourceGroup }} \ + --name ${{ inputs.dbInstanceName }} \ + --query "fullyQualifiedDomainName" -o tsv) + echo "Create a database in the PostgreSQL server" + az postgres flexible-server db create --resource-group ${{ inputs.resourceGroup }} \ + --server-name ${{ inputs.dbInstanceName }} \ + --database-name ${{ inputs.databaseName }} + + echo "serverHost=${host}" >> "$GITHUB_ENV" + echo "uamiId=${uamiId}" >> "$GITHUB_ENV" + + - name: Set outputs + id: resource_outputs + shell: bash + run: | + echo "uamiId=${{ env.uamiId }}" >> "$GITHUB_OUTPUT" + echo "serverHost=${{ env.serverHost }}" >> "$GITHUB_OUTPUT" diff --git a/.github/actions/it/action.yml b/.github/actions/it/action.yml new file mode 100644 index 000000000..c7774892f --- /dev/null +++ b/.github/actions/it/action.yml @@ -0,0 +1,676 @@ +name: 'IT Validation Workflows' +description: 'Execute validation workflows based on a validation plan' +inputs: + it_file: + description: 'Path to the validation plan file' + required: true + github_token: + description: 'GitHub token for API access' + required: true + default: ${{ github.token }} + +outputs: + results: + description: 'JSON string containing the results of all workflow executions' + value: ${{ steps.collect-results.outputs.results }} + report_timestamp: + description: 'Timestamp of the generated report' + value: ${{ steps.generate-report.outputs.timestamp }} + report_url: + description: 'URL to the generated report' + value: ${{ steps.output-urls.outputs.report_url }} + +runs: + using: 'composite' + steps: + - name: Read validation plan + id: set-matrix + shell: bash + run: | + PLAN_FILE="${{ inputs.it_file }}" + echo "Looking for plan file: $PLAN_FILE" + + if [ ! -f "$PLAN_FILE" ]; then + echo "Error: Plan file $PLAN_FILE not found" + echo "Current working directory: $(pwd)" + echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE" + echo "Listing current directory:" + ls -la + exit 1 + fi + + echo "Successfully found plan file: $PLAN_FILE" + + # Create matrix from plan + MATRIX=$(jq -c '.validation_scenarios | map({ + workflow: .workflow, + run_mode: (.run_mode // "parallel"), + scenarios: .scenarios + })' "$PLAN_FILE") + + echo "matrix=$MATRIX" >> $GITHUB_OUTPUT + + - name: Execute validation workflows + id: execute-workflows + uses: actions/github-script@v7 + env: + GITHUB_TOKEN: ${{ inputs.github_token }} + with: + script: | + const matrix = ${{ steps.set-matrix.outputs.matrix }}; + const allWorkflowRuns = []; + + for (const item of matrix) { + const workflow = item.workflow; + const runMode = item.run_mode; + const scenarios = item.scenarios; + const workflowRuns = []; + + console.log(`Starting to trigger workflow: ${workflow}`); + console.log(`Run mode: ${runMode}`); + console.log(`Number of scenarios to process: ${scenarios.length}`); + console.log(`Current owner: ${context.repo.owner}`); + console.log(`Current repo: ${context.repo.repo}`); + + if (runMode === 'serial') { + console.log('Running scenarios in serial mode'); + + for (const scenario of scenarios) { + try { + const scenarioName = scenario.scenario; + const scenarioInputs = scenario.inputs; + + console.log(`Triggering ${workflow} with scenario "${scenarioName}":`, JSON.stringify(scenarioInputs, null, 2)); + + // The github rest api for workflow dispatch requires all inputs to be strings. + // We need to convert any object values to JSON strings. + const inputs = Object.fromEntries( + Object.entries(scenarioInputs).map(([key, value]) => { + if (typeof value === 'object' && value !== null) { + return [key, JSON.stringify(value)]; + } + return [key, value]; + }) + ); + + // Trigger the workflow + const dispatchResponse = await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: workflow, + ref: context.ref, + inputs: inputs + }); + + console.log(`Workflow dispatch response:`, JSON.stringify(dispatchResponse.data, null, 2)); + + // Wait for 5 seconds for the workflow to be created + console.log('Waiting 5 seconds for workflow to be created...'); + await new Promise(resolve => setTimeout(resolve, 5000)); + + // Get the latest workflow run + let attempts = 0; + const maxAttempts = 5; + let run = null; + + while (attempts < maxAttempts) { + console.log(`Attempt ${attempts + 1} to find workflow run...`); + const runs = await github.rest.actions.listWorkflowRuns({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: workflow + }); + + if (runs.data.workflow_runs && runs.data.workflow_runs.length > 0) { + const potentialRun = runs.data.workflow_runs[0]; + // Get detailed run information + const runDetails = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: potentialRun.id + }); + + console.log(`Found workflow run:`, JSON.stringify({ + id: runDetails.data.id, + status: runDetails.data.status, + created_at: runDetails.data.created_at, + head_branch: runDetails.data.head_branch, + html_url: runDetails.data.html_url + }, null, 2)); + + run = runDetails.data; + break; + } + + console.log('No matching workflow run found, waiting 5 seconds...'); + await new Promise(resolve => setTimeout(resolve, 5000)); + attempts++; + } + + if (!run) { + console.log('Failed to find workflow run after all attempts'); + continue; + } + + // Wait for this workflow to complete before triggering the next one + console.log(`Waiting for workflow run ${run.id} to complete...`); + let status = run.status; + let waitAttempts = 0; + const maxWaitAttempts = 90; // 90 minutes maximum wait time + + while (status !== 'completed' && waitAttempts < maxWaitAttempts) { + // Wait for 60 seconds between checks + await new Promise(resolve => setTimeout(resolve, 60000)); + + // Get the workflow run status + const runData = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: run.id + }); + + status = runData.data.status; + console.log(`Workflow ${workflow} status: ${status} (wait attempt ${waitAttempts + 1}/${maxWaitAttempts})`); + + // If the workflow is still queued or in progress, continue waiting + if (status === 'queued' || status === 'in_progress') { + waitAttempts++; + continue; + } + + // If the workflow is completed, break the loop + if (status === 'completed') { + console.log(`Workflow ${workflow} completed with conclusion: ${runData.data.conclusion}`); + break; + } + + // If we get here, the status is something unexpected + console.log(`Unexpected status for workflow ${workflow}: ${status}`); + waitAttempts++; + } + + if (status !== 'completed') { + console.log(`Workflow ${workflow} did not complete within the maximum wait time. Moving to next scenario.`); + } + + workflowRuns.push({ + workflow: workflow, + scenario: scenarioInputs, + scenarioName: scenarioName, + runId: run.id, + runUrl: run.html_url, + startTime: run.created_at + }); + + console.log(`Successfully processed workflow run: ${run.id}`); + } catch (error) { + console.error(`Error processing scenario:`, error); + console.error(`Error details:`, JSON.stringify(error, null, 2)); + } + } + } else { + console.log('Running scenarios in parallel mode'); + + for (const scenario of scenarios) { + try { + const scenarioName = scenario.scenario; + const scenarioInputs = scenario.inputs; + + console.log(`Triggering ${workflow} with scenario "${scenarioName}":`, JSON.stringify(scenarioInputs, null, 2)); + + // The github rest api for workflow dispatch requires all inputs to be strings. + // We need to convert any object values to JSON strings. + const inputs = Object.fromEntries( + Object.entries(scenarioInputs).map(([key, value]) => { + if (typeof value === 'object' && value !== null) { + return [key, JSON.stringify(value)]; + } + return [key, value]; + }) + ); + + // Trigger the workflow + const dispatchResponse = await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: workflow, + ref: context.ref, + inputs: inputs + }); + + console.log(`Workflow dispatch response:`, JSON.stringify(dispatchResponse.data, null, 2)); + + // Wait for 5 seconds for the workflow to be created + console.log('Waiting 5 seconds for workflow to be created...'); + await new Promise(resolve => setTimeout(resolve, 5000)); + + // Get the latest workflow run + let attempts = 0; + const maxAttempts = 5; + let run = null; + + while (attempts < maxAttempts) { + console.log(`Attempt ${attempts + 1} to find workflow run...`); + const runs = await github.rest.actions.listWorkflowRuns({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: workflow + }); + + if (runs.data.workflow_runs && runs.data.workflow_runs.length > 0) { + const potentialRun = runs.data.workflow_runs[0]; + // Get detailed run information + const runDetails = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: potentialRun.id + }); + + console.log(`Found workflow run:`, JSON.stringify({ + id: runDetails.data.id, + status: runDetails.data.status, + created_at: runDetails.data.created_at, + head_branch: runDetails.data.head_branch, + html_url: runDetails.data.html_url + }, null, 2)); + + run = runDetails.data; + break; + } + + console.log('No matching workflow run found, waiting 5 seconds...'); + await new Promise(resolve => setTimeout(resolve, 5000)); + attempts++; + } + + if (!run) { + console.log('Failed to find workflow run after all attempts'); + continue; + } + + workflowRuns.push({ + workflow: workflow, + scenario: scenarioInputs, + scenarioName: scenarioName, + runId: run.id, + runUrl: run.html_url, + startTime: run.created_at + }); + + console.log(`Successfully tracked workflow run: ${run.id}`); + } catch (error) { + console.error(`Error processing scenario:`, error); + console.error(`Error details:`, JSON.stringify(error, null, 2)); + } + } + } + + allWorkflowRuns.push(...workflowRuns); + } + + console.log(`Total workflow runs tracked: ${allWorkflowRuns.length}`); + console.log('Workflow runs:', JSON.stringify(allWorkflowRuns, null, 2)); + + core.setOutput('workflow_runs', JSON.stringify(allWorkflowRuns)); + + - name: Wait for workflows and collect results + id: collect-results + uses: actions/github-script@v7 + env: + GITHUB_TOKEN: ${{ inputs.github_token }} + with: + script: | + const workflowRuns = JSON.parse('${{ steps.execute-workflows.outputs.workflow_runs }}'); + const results = []; + + for (const run of workflowRuns) { + console.log(`Processing workflow ${run.workflow} run ${run.runId}...`); + + // Get the current workflow run status + const runData = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: run.runId + }); + + let status = runData.data.status; + + // If the workflow is already completed (likely from serial execution), use it directly + if (status === 'completed') { + console.log(`Workflow ${run.workflow} is already completed with conclusion: ${runData.data.conclusion}`); + results.push({ + workflow: run.workflow, + scenario: run.scenario, + scenarioName: run.scenarioName, + status: runData.data.conclusion, + runId: run.runId, + runUrl: run.runUrl, + startTime: run.startTime, + endTime: runData.data.updated_at + }); + continue; + } + + // For workflows that are still running (parallel mode), wait for completion + console.log(`Waiting for workflow ${run.workflow} run ${run.runId}...`); + + let attempts = 0; + const maxAttempts = 60; // 60 minutes maximum wait time + + while (status !== 'completed' && attempts < maxAttempts) { + try { + // Wait for 60 seconds between checks + await new Promise(resolve => setTimeout(resolve, 60000)); + + // Get the workflow run status + const runData = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: run.runId + }); + + status = runData.data.status; + console.log(`Workflow ${run.workflow} status: ${status} (attempt ${attempts + 1}/${maxAttempts})`); + + // If the workflow is still queued or in progress, continue waiting + if (status === 'queued' || status === 'in_progress') { + attempts++; + continue; + } + + // If the workflow is completed, break the loop + if (status === 'completed') { + break; + } + + // If we get here, the status is something unexpected + console.log(`Unexpected status for workflow ${run.workflow}: ${status}`); + attempts++; + } catch (error) { + console.log(`Error checking workflow status: ${error.message}`); + attempts++; + } + } + + if (status !== 'completed') { + console.log(`Workflow ${run.workflow} did not complete within the maximum wait time`); + results.push({ + workflow: run.workflow, + scenario: run.scenario, + scenarioName: run.scenarioName, + status: 'timeout', + runId: run.runId, + runUrl: run.runUrl, + startTime: run.startTime, + endTime: new Date().toISOString() + }); + continue; + } + + // Get the final workflow run data + const finalRunData = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: run.runId + }); + + results.push({ + workflow: run.workflow, + scenario: run.scenario, + scenarioName: run.scenarioName, + status: finalRunData.data.conclusion, + runId: run.runId, + runUrl: run.runUrl, + startTime: run.startTime, + endTime: finalRunData.data.updated_at + }); + } + + core.setOutput('results', JSON.stringify(results)); + + - name: Generate Markdown report + id: generate-report + shell: bash + run: | + TIMESTAMP=$(date +"%Y-%m-%d-%H-%M-%S") + echo "timestamp=$TIMESTAMP" >> $GITHUB_OUTPUT + echo "Current directory: $(pwd)" + + # Generate table rows and summary + RESULTS='${{ steps.collect-results.outputs.results }}' + rows="" + total=0 + success=0 + failure=0 + timeout=0 + cancelled=0 + other_failed=0 + for row in $(echo "$RESULTS" | jq -r '.[] | @base64'); do + _jq() { + echo ${row} | base64 --decode | jq -r "$1" + } + workflow=$(_jq '.workflow') + scenario_name=$(_jq '.scenarioName // empty') + scenario=$(_jq '.scenario | if type=="object" then to_entries | map("\(.key): \(.value)") | join(", ") else tostring end') + status=$(_jq '.status') + runUrl=$(_jq '.runUrl') + startTime=$(_jq '.startTime') + endTime=$(_jq '.endTime') + + # Use scenario name if available, otherwise use the scenario details + display_scenario="${scenario_name:-${scenario}}" + + # Calculate duration + start=$(date -d "$startTime" +%s) + end=$(date -d "$endTime" +%s) + duration=$((end - start)) + duration_str=$(printf '%dh:%dm:%ds' $((duration/3600)) $((duration%3600/60)) $((duration%60))) + + # Count status + total=$((total+1)) + if [ "$status" = "success" ]; then + success=$((success+1)) + elif [ "$status" = "failure" ]; then + failure=$((failure+1)) + elif [ "$status" = "timeout" ]; then + timeout=$((timeout+1)) + elif [ "$status" = "cancelled" ]; then + cancelled=$((cancelled+1)) + else + # Any other non-success status + other_failed=$((other_failed+1)) + fi + + # Create table row + rows+="| ${workflow} | \`${display_scenario}\` | ${status} | ${duration_str} | [View Run](${runUrl}) |\n" + done + + # Create a temporary file with the content + { + echo "# Validation Workflow Results" + echo "" + echo "## Summary" + echo "- Total Workflows: ${total}" + echo "- Successful: ${success}" + echo "- Failed: ${failure}" + echo "- Timed Out: ${timeout}" + echo "- Cancelled: ${cancelled}" + echo "- Other Failed: ${other_failed}" + echo "" + echo "## Detailed Results" + echo "" + echo "| Workflow | Scenario | Status | Duration | Run URL |" + echo "|----------|----------|---------|-----------|----------|" + echo -e "${rows}" + echo "" + echo "## Execution Notes" + echo "- Workflows marked with \`run_mode: serial\` are executed one after another" + echo "- Other workflows are executed in parallel" + } > "${TIMESTAMP}-report.md" + + - name: Upload report + uses: actions/upload-artifact@v4.6.2 + with: + name: validation-report-${{ steps.generate-report.outputs.timestamp }} + path: ${{ steps.generate-report.outputs.timestamp }}-report.md + + - name: Setup Git + shell: bash + run: | + git config --global user.name "GitHub Actions" + git config --global user.email "actions@github.com" + + - name: Create/Update IT Branch + shell: bash + run: | + # Debug information + echo "Current directory: $(pwd)" + echo "Listing files in current directory:" + ls -la + echo "Listing files in workspace:" + ls -la $GITHUB_WORKSPACE + + # Find the report file + REPORT_FILE=$(find $GITHUB_WORKSPACE -name "${{ steps.generate-report.outputs.timestamp }}-report.md") + echo "Found report file at: $REPORT_FILE" + + if [ ! -f "$REPORT_FILE" ]; then + echo "Error: Report file not found!" + exit 1 + fi + + # Fetch all branches + git fetch origin + + # Check if it branch exists remotely + if git ls-remote --exit-code --heads origin it; then + echo "it branch exists. Checking out..." + git checkout it + git pull origin it + else + echo "it branch does not exist. Creating new it branch from current HEAD..." + git checkout -b it + fi + + # Use existing it-report directory if present, otherwise create it + if [ -d "it-report" ]; then + echo "it-report directory exists. Using existing directory." + else + echo "it-report directory does not exist. Creating it." + mkdir it-report + fi + + # Copy the report to it-report directory + cp "$REPORT_FILE" it-report/ + + # Add and commit the report + git add it-report/${{ steps.generate-report.outputs.timestamp }}-report.md + git commit -m "Add validation report ${{ steps.generate-report.outputs.timestamp }}" || echo "Nothing to commit." + + # Push to the it branch + git push origin it + + - name: Output Report URL + id: output-urls + shell: bash + run: | + REPORT_URL="https://github.com/${{ github.repository }}/blob/it/it-report/${{ steps.generate-report.outputs.timestamp }}-report.md" + RAW_REPORT_URL="https://raw.githubusercontent.com/${{ github.repository }}/it/it-report/${{ steps.generate-report.outputs.timestamp }}-report.md" + + echo "::notice::📊 Validation Report URL: $REPORT_URL" + echo "::notice::📊 Raw Report URL: $RAW_REPORT_URL" + echo "report_url=$REPORT_URL" >> $GITHUB_OUTPUT + + - name: Check workflow results and fail if any failed + shell: bash + run: | + RESULTS='${{ steps.collect-results.outputs.results }}' + + # Parse results and check for failures + failed_workflows=() + timeout_workflows=() + cancelled_workflows=() + other_failed_workflows=() + total=0 + success=0 + failure=0 + timeout=0 + cancelled=0 + other_failed=0 + + for row in $(echo "$RESULTS" | jq -r '.[] | @base64'); do + _jq() { + echo ${row} | base64 --decode | jq -r "$1" + } + workflow=$(_jq '.workflow') + scenario_name=$(_jq '.scenarioName // empty') + scenario=$(_jq '.scenario | if type=="object" then to_entries | map("\(.key): \(.value)") | join(", ") else tostring end') + status=$(_jq '.status') + runUrl=$(_jq '.runUrl') + + # Use scenario name if available, otherwise use the scenario details + display_scenario="${scenario_name:-${scenario}}" + + # Count status and track failed workflows + total=$((total+1)) + if [ "$status" = "success" ]; then + success=$((success+1)) + elif [ "$status" = "failure" ]; then + failure=$((failure+1)) + failed_workflows+=("${workflow} (${display_scenario}): ${runUrl}") + elif [ "$status" = "timeout" ]; then + timeout=$((timeout+1)) + timeout_workflows+=("${workflow} (${display_scenario}): ${runUrl}") + elif [ "$status" = "cancelled" ]; then + cancelled=$((cancelled+1)) + cancelled_workflows+=("${workflow} (${display_scenario}): ${runUrl}") + else + # Any other non-success status should be treated as a failure + other_failed=$((other_failed+1)) + other_failed_workflows+=("${workflow} (${display_scenario}) [${status}]: ${runUrl}") + fi + done + + # Display summary + echo "::notice::📊 Workflow Execution Summary:" + echo "::notice:: Total: ${total}, Success: ${success}, Failed: ${failure}, Timeout: ${timeout}, Cancelled: ${cancelled}, Other Failed: ${other_failed}" + + # If there are failed workflows, display them and fail the IT + if [ ${#failed_workflows[@]} -gt 0 ]; then + echo "::error::❌ The following workflows failed:" + for failed in "${failed_workflows[@]}"; do + echo "::error:: - ${failed}" + done + fi + + # If there are timeout workflows, display them and fail the IT + if [ ${#timeout_workflows[@]} -gt 0 ]; then + echo "::error::⏰ The following workflows timed out:" + for timeout in "${timeout_workflows[@]}"; do + echo "::error:: - ${timeout}" + done + fi + + # If there are cancelled workflows, display them and fail the IT + if [ ${#cancelled_workflows[@]} -gt 0 ]; then + echo "::error::🚫 The following workflows were cancelled:" + for cancelled in "${cancelled_workflows[@]}"; do + echo "::error:: - ${cancelled}" + done + fi + + # If there are other failed workflows, display them and fail the IT + if [ ${#other_failed_workflows[@]} -gt 0 ]; then + echo "::error::❌ The following workflows failed with other statuses:" + for other_failed in "${other_failed_workflows[@]}"; do + echo "::error:: - ${other_failed}" + done + fi + + # Fail the IT workflow if any workflow failed, timed out, was cancelled, or had other failure statuses + if [ ${#failed_workflows[@]} -gt 0 ] || [ ${#timeout_workflows[@]} -gt 0 ] || [ ${#cancelled_workflows[@]} -gt 0 ] || [ ${#other_failed_workflows[@]} -gt 0 ]; then + echo "::error::❌ IT workflow failed because ${#failed_workflows[@]} workflow(s) failed, ${#timeout_workflows[@]} workflow(s) timed out, ${#cancelled_workflows[@]} workflow(s) were cancelled, and ${#other_failed_workflows[@]} workflow(s) had other failure statuses." + exit 1 + fi + + echo "::notice::✅ All workflows completed successfully!" \ No newline at end of file diff --git a/.github/it/README.md b/.github/it/README.md new file mode 100644 index 000000000..268a55c15 --- /dev/null +++ b/.github/it/README.md @@ -0,0 +1,286 @@ +# IT Validation Configuration + +## Overview + +The IT validation system is a comprehensive integration testing framework designed to validate Oracle WebLogic Server deployments on Azure across multiple scenarios and configurations. It automates the execution of various deployment scenarios, monitors their progress, and generates detailed reports to ensure the reliability and quality of the Azure WebLogic templates. + +### Key Features + +- **Multi-Scenario Testing**: Execute multiple test scenarios simultaneously or sequentially +- **Flexible Execution Modes**: Support for both parallel and serial execution modes +- **Comprehensive Reporting**: Detailed reports with success/failure statistics and execution URLs +- **Automated Monitoring**: Real-time tracking of workflow execution with timeout protection +- **Resource Management**: Efficient cleanup and resource optimization for cost-effective testing + +### Use Cases + +- **Regression Testing**: Validate WebLogic templates after code changes or updates +- **Release Validation**: Comprehensive testing before production releases +- **Configuration Testing**: Verify different deployment configurations and parameters +- **Performance Monitoring**: Track deployment times and resource utilization + +## Table of Contents + +- [System Architecture](#system-architecture) +- [Configuration Structure](#configuration-structure) + - [Scenarios Structure](#scenarios-structure) + - [Execution Modes](#execution-modes) +- [How It Works](#how-it-works) +- [Available Files](#available-files) + - [File Content Overview](#file-content-overview) +- [Getting Started](#getting-started) + - [Quick Start Guide](#quick-start-guide) + - [Prerequisites](#prerequisites) +- [IT Action Usage](#it-action-usage) + - [Action Inputs](#action-inputs) + - [Action Outputs](#action-outputs) +- [Structure Requirements](#structure-requirements) +- [Serial vs Parallel Execution](#serial-vs-parallel-execution) +- [Report Generation](#report-generation) + - [Status Tracking](#status-tracking) + - [Accessing Reports](#accessing-reports) +- [Error Handling](#error-handling) +- [Trouble Shooting](#trouble-shooting) + + +## System Architecture + +The IT validation system consists of: + +1. **Validation Plan Files** (this directory): JSON files defining what to test +2. **IT Action** (`/.github/actions/it/action.yml`): Reusable composite action that executes the plans +3. **IT Workflows** (`/.github/workflows/it-validation-*.yaml`): Workflows that trigger the action with specific plans +3. **Target Workflows** (`/.github/workflows/testWls*.yml` and `buildWls*.yml`): The actual validation workflows that get executed + +## Configuration Structure + +The validation plan files use the following structure: + +### Scenarios Structure +Each validation plan defines scenarios with descriptive names: + +```json +{ + "validation_scenarios": [ + { + "workflow": "testWlsVmAdmin.yml", + "run_mode": "serial", + "scenarios": [ + { + "scenario": "Test Admin Server on VM with mssqlserver", + "inputs": { + "location": "centralus" + } + } + ] + } + ] +} +``` + +### Execution Modes + +You can control how scenarios within a workflow are executed by using the optional `run_mode` property: + +- **`"run_mode": "serial"`**: Scenarios are executed one after another. Each scenario must complete before the next one starts. +- **`"run_mode": "parallel"`** or **no `run_mode` specified**: Scenarios are executed simultaneously (default behavior). + +**Example with serial execution:** +```json +{ + "validation_scenarios": [ + { + "workflow": "testWlsVmCluster.yml", + "run_mode": "serial", + "scenarios": [ + { + "scenario": "First scenario", + "inputs": { /* ... */ } + }, + { + "scenario": "Second scenario", + "inputs": { /* ... */ } + } + ] + } + ] +} +``` + +**When to use serial mode:** +- Resource-intensive scenarios that might conflict if run simultaneously +- Scenarios that need to run in a specific order +- Limited resource environments where parallel execution might cause failures + +## How It Works + +1. **IT Workflows**: The `it-validation-*.yaml` workflows are triggered (manually or scheduled) + +2. **Plan File Mapping**: Each IT workflow maps its input to a specific validation plan file in this directory + +3. **Action Execution**: The workflow calls the IT action (`/.github/actions/it/action.yml`) with the plan file path + +4. **Plan Processing**: The action reads the validation plan and processes each scenario + +5. **Execution Mode**: The optional `run_mode` property controls whether scenarios are executed serially or in parallel + +6. **Workflow Triggering**: The action triggers the specified target workflows with the scenario inputs + +7. **Monitoring**: The action monitors workflow execution and waits for completion + +8. **Reporting**: Results are compiled into comprehensive reports and stored in the `it` branch + +## Available Files + +- `validation-plan-aks.json`: Azure Kubernetes Service (AKS) validation scenarios for WebLogic Server deployments +- `validation-plan-build.json`: Build-only validation scenarios for template compilation and syntax checking +- `validation-plan-vm-admin.json`: WebLogic Admin Server on VM validation scenarios +- `validation-plan-vm-cluster.json`: WebLogic Configured Cluster on VM validation scenarios +- `validation-plan-vm-dynamic-cluster.json`: WebLogic Dynamic Cluster on VM validation scenarios + +### File Content Overview + +Each validation plan targets specific WebLogic deployment scenarios: + +- **AKS Plans**: Test WebLogic Server deployments on Azure Kubernetes Service with various database configurations +- **VM Plans**: Test WebLogic Server deployments on Azure Virtual Machines in different topologies (Admin Server, Configured Cluster, Dynamic Cluster) +- **Build Plans**: Validate artifact compilation and template syntax without actual deployments + +## Getting Started + +### Quick Start Guide + +1. **Choose a Validation Plan**: Select the appropriate validation plan file based on your testing needs: + - For AKS deployments: `validation-plan-aks.json` + - For Admin Server on VM: `validation-plan-vm-admin.json` + - For Configured Cluster on VM: `validation-plan-vm-cluster.json` + - For Dynamic Cluster on VM: `validation-plan-vm-dynamic-cluster.json` + - For build validation only: `validation-plan-build.json` + +2. **Trigger IT Validation**: Use the GitHub Actions interface to manually trigger a IT validation workflow: + - Go to the "Actions" tab in the repository + - Select the appropriate `it-validation-*` workflow: + - `IT Validation for AKS` - for AKS deployments + - `IT Validation for VM Admin` - for Admin Server on VM + - `IT Validation for VM Cluster` - for Configured Cluster on VM + - `IT Validation for VM Dynamic Cluster` - for Dynamic Cluster on VM + - `IT Validation for Build` - for build-only validation + - Click "Run workflow" and select your desired validation plan + +3. **Monitor Progress**: Track the execution progress in the Actions tab and view real-time logs + +4. **Review Results**: Check the generated reports in the `it` branch under `it-report/` directory + +### Prerequisites + +Before using the IT validation system, ensure: + +- [ ] Azure subscription with appropriate permissions +- [ ] GitHub repository with Actions enabled +- [ ] Required secrets configured in repository settings. The repository secrets set by the [setup-credentials.sh](../workflows/setup-credentials.sh) script must be set with current and valid values before any of these workflows will run. +- [ ] Access to the `it` branch for report storage + +## IT Action Usage + +The validation plans are consumed by the IT action located at `/.github/actions/it/action.yml`. + +### Action Inputs + +| Input | Description | Required | +|-------|-------------|----------| +| `it_file` | Path to the validation plan file | Yes | + +### Action Outputs + +| Output | Description | +|--------|-------------| +| `results` | JSON string containing the results of all workflow executions | +| `report_timestamp` | Timestamp of the generated report | +| `report_url` | URL to the generated report on the IT branch | + +## Structure Requirements + +- Each plan must have a `validation_scenarios` array +- Each item in the array must have a `workflow` and `scenarios` field +- Each scenario must have a `scenario` name and an `inputs` object +- The optional `run_mode` field can be set to `"serial"` or `"parallel"` (default) +- Only the `inputs` object content is passed to the target workflow + +## Serial vs Parallel Execution + +### Parallel Execution (Default) +- All scenarios within a workflow are triggered simultaneously +- Faster overall execution time +- Suitable for independent scenarios that don't compete for resources + +### Serial Execution +- Scenarios are executed one after another +- Each scenario must complete before the next one starts +- Longer overall execution time but better resource management +- Includes waiting and monitoring between scenarios +- Recommended for resource-intensive workloads or debugging + +## Report Generation + +The IT action generates comprehensive reports that include: + +- **Summary Statistics**: Total workflows, success/failure counts including cancelled and timeout scenarios +- **Detailed Results**: Individual workflow results with duration and status +- **Execution URLs**: Direct links to workflow runs +- **Execution Notes**: Information about serial vs parallel execution + +Reports are: +1. Uploaded as GitHub Actions artifacts +2. Committed to the `it` branch in the `it-report/` directory +3. Accessible via the repository's IT branch + +### Status Tracking + +The system tracks all execution outcomes: +- **Success**: Workflows completed successfully +- **Failure**: Workflows failed during execution +- **Timeout**: Workflows exceeded the 60-minute timeout limit +- **Cancelled**: Workflows manually cancelled by users +- **Other Failed**: Workflows with any other non-success status + +### Accessing Reports + +Reports can be accessed in multiple ways: + +1. **GitHub Actions Artifacts**: Download reports directly from the workflow run artifacts +2. **IT Branch**: Browse reports in the `it` branch under `it-report/` directory +3. **Direct Links**: Use the `report_url` output from the IT action +4. **API Access**: Programmatically access reports via GitHub API + +#### Report File Naming Convention + +Reports follow the naming pattern: `report-YYYYMMDD-HHMMSS.json` + +Example: `report-20250804-103000.json` (August 4, 2025 at 10:30:00 UTC) + +## Error Handling + +The IT action includes robust error handling: +- **Timeout Protection**: 60-minute maximum wait time per workflow +- **Failure Detection**: IT workflow fails if any triggered workflow fails, times out, or is cancelled + +## Trouble Shooting + +### Debugging with tmate + +One of the biggest pain points to develop GitHub actions for our Java EE solution offerings is that it's hard to debug them by direct interacting with the host system on which the actual Actions are running. + +I found a GitHub action `tmate` which unlocks the door for debugging GitHub actions using SSH or Web shell, pls refer to [Debugging with tmate](https://github.com/marketplace/actions/debugging-with-tmate) or to the [tmate docs](https://mxschmitt.github.io/action-tmate/) for detailed how-to instructions. + +And here is an example where `tmate` was applied in `integration-test` workflow of `liberty-on-aks` repo: +* https://github.com/WASdev/azure.liberty.aks/pull/62/files#diff-b6766eb8febc0c51651250cd0cdfb44c4f0d3256470d88e62bf82fd46aa73ae0R119-R121 + + +## Authentication of the tmate session. +> Refer to this [issue](https://github.com/mxschmitt/action-tmate/issues/163)’s [comment](https://github.com/mxschmitt/action-tmate/issues/163#issuecomment-1651436411), + +this [action](https://github.com/mxschmitt/action-tmate) uses the ssh public key from the github account as `authorised_keys`. +So if you have multiple private keys in your local machine, you may need to specify the private key used for `*.tmate.io` in your `~/.ssh/config` file. + +![tmate-sshkey.png](tmate-sshkey.png) + diff --git a/.github/it/tmate-sshkey.png b/.github/it/tmate-sshkey.png new file mode 100644 index 000000000..7e4e383f6 Binary files /dev/null and b/.github/it/tmate-sshkey.png differ diff --git a/.github/it/validation-plan-aks.json b/.github/it/validation-plan-aks.json new file mode 100644 index 000000000..d59d08a1a --- /dev/null +++ b/.github/it/validation-plan-aks.json @@ -0,0 +1,36 @@ +{ + "validation_scenarios": [ + { + "workflow": "testWlsAksWithDependencyCreation.yml", + "run_mode": "serial", + "scenarios": [ + { + "scenario": "Deploy with passwordless postgresql", + "inputs": { + "location": "centralus", + "databaseType": "postgresql-passwordless(flexible)" + } + }, + { + "scenario": "Disable the App Gateway Ingress Controller", + "inputs": { + "location": "centralus", + "configurations_for_it": { + "enableAppGWIngress": "false" + } + } + }, + { + "scenario": "Bring you own AKS clusters and using postgresql", + "inputs": { + "location": "centralus", + "configurations_for_it": { + "createAKSCluster": "false", + "aksClusterName": "my-existing-aks-cluster" + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/.github/it/validation-plan-build.json b/.github/it/validation-plan-build.json new file mode 100644 index 000000000..50ff53c38 --- /dev/null +++ b/.github/it/validation-plan-build.json @@ -0,0 +1,55 @@ +{ + "validation_scenarios": [ + { + "workflow": "buildWlsAksArtifact.yml", + "scenarios": [ + { + "scenario": "Build WLS on AKS artifact", + "inputs": { + } + + } + ] + }, + { + "workflow": "buildWlsVm4AsArtifact.yml", + "scenarios": [ + { + "scenario": "Build Admin Server VM artifact", + "inputs": { + } + } + ] + }, + { + "workflow": "buildWlsVm4CcArtifact.yml", + "scenarios": [ + { + "scenario": "Build Configured Cluster VM artifact", + "inputs": { + } + } + ] + }, + { + "workflow": "buildWlsVm4DcArtifact.yml", + "scenarios": [ + { + "scenario": "Build Dynamic Cluster VM artifact", + "inputs": { + } + } + ] + }, + { + "workflow": "buildWlsVm4SnArtifact.yml", + "scenarios": [ + { + "scenario": "Build Single Node VM artifact", + "inputs": { + } + } + ] + } + ] +} \ No newline at end of file diff --git a/.github/it/validation-plan-vm-admin.json b/.github/it/validation-plan-vm-admin.json new file mode 100644 index 000000000..26090ed7a --- /dev/null +++ b/.github/it/validation-plan-vm-admin.json @@ -0,0 +1,33 @@ +{ + "validation_scenarios": [ + { + "workflow": "testWlsVmAdmin.yml", + "scenarios": [ + { + "scenario": "Test Admin Server on VM with mssqlserver", + "inputs": { + "location": "centralus" + } + }, + { + "scenario": "Test Admin Server on VM with passwordless postgresql", + "inputs": { + "location": "centralus", + "databaseType": "postgresql-passwordless(flexible)" + } + }, + { + "scenario": "Bring your own VNET for Admin Server on VM", + "inputs": { + "location": "centralus", + "configurations_for_it": { + "virtualNetworkNewOrExisting": "existing", + "virtualNetworkName": "myvirtualNetworkName-vm-admin", + "subnetName": "mySubnet-vm-admin" + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/.github/it/validation-plan-vm-cluster.json b/.github/it/validation-plan-vm-cluster.json new file mode 100644 index 000000000..fbe0f006a --- /dev/null +++ b/.github/it/validation-plan-vm-cluster.json @@ -0,0 +1,37 @@ +{ + "validation_scenarios": [ + { + "workflow": "testWlsVmCluster.yml", + "run_mode": "serial", + "scenarios": [ + { + "scenario": "Test Configured Cluster on VM with mssqlserver", + "inputs": { + "location": "centralus", + "databaseType": "mssqlserver" + } + }, + { + "scenario": "Bring your own VNET for Cluster on VM", + "inputs": { + "location": "centralus", + "databaseType": "mssqlserver", + "configurations_for_it": { + "virtualNetworkNewOrExisting": "existing", + "virtualNetworkName": "my-existing-cluster-vnet", + "subnetForCluster": "my-existing-cluster-subnet-for-cluster", + "subnetForAppGateway": "my-existing-cluster-subnet-for-app-gateway" + } + } + }, + { + "scenario": "Test Configured Cluster on VM with PostgreSQL passwordless", + "inputs": { + "location": "centralus", + "databaseType": "postgresql-passwordless(flexible)" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/.github/it/validation-plan-vm-dynamic-cluster.json b/.github/it/validation-plan-vm-dynamic-cluster.json new file mode 100644 index 000000000..f7266db3a --- /dev/null +++ b/.github/it/validation-plan-vm-dynamic-cluster.json @@ -0,0 +1,24 @@ +{ + "validation_scenarios": [ + { + "workflow": "testWlsVmDynamicCluster.yml", + "run_mode": "serial", + "scenarios": [ + { + "scenario": "Test Dynamic Cluster on VM with mssqlserver", + "inputs": { + "location": "centralus", + "databaseType": "mssqlserver" + } + }, + { + "scenario": "Test Dynamic Cluster on VM with PostgreSQL passwordless", + "inputs": { + "location": "centralus", + "databaseType": "postgresql-passwordless(flexible)" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/.github/variables/vm-dependencies.env b/.github/variables/vm-dependencies.env index 84d9c771d..3e181d08a 100644 --- a/.github/variables/vm-dependencies.env +++ b/.github/variables/vm-dependencies.env @@ -1,2 +1,2 @@ refArmttk=6b75cb7a3f65234995a2019fcae20a9b2c2d8635 -azCliVersion=2.60.0 +azCliVersion=2.72.0 diff --git a/.github/workflows/buildWlsVm4AsArtifact.yml b/.github/workflows/buildWlsVm4AsArtifact.yml index de97f9c78..ff53bc5d3 100644 --- a/.github/workflows/buildWlsVm4AsArtifact.yml +++ b/.github/workflows/buildWlsVm4AsArtifact.yml @@ -11,16 +11,14 @@ on: description: 'Specify which pids to use, oracle or microsoft.' required: true default: 'oracle' - ref: - description: 'Specify Git Ref if needed.' - required: false - default: 'refs/heads/main' + # Sample cURL - # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "vms-admin-package", "client_payload": {"pidType": "microsoft", "ref": "refs/heads/main"}}' + # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "vms-admin-package", "client_payload": {"pidType": "microsoft"}}' env: offerName: "arm-oraclelinux-wls-admin" repoName: "weblogic-azure" - repoOwner: ${{ secrets.USER_NAME }} + repoOwner: ${{ github.repository_owner }} + ref: ${{ github.ref_name }} jobs: package: @@ -31,24 +29,17 @@ jobs: run: | if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then pidType=${{ github.event.inputs.pidType }} - ref=${{ github.event.inputs.ref }} else pidType=${{ github.event.client_payload.pidType }} - ref=${{ github.event.client_payload.ref }} fi if [ -z "$pidType" ]; then pidType='microsoft' fi - if [ -z "$ref" ]; then - ref='refs/heads/main' - fi - echo "##[set-output name=pidType;]${pidType}" - echo "##[set-output name=ref;]${ref}" echo "pidType=${pidType}" >> $GITHUB_ENV - echo "ref=${ref}" >> $GITHUB_ENV + - uses: actions/checkout@v2.3.4 - name: Set up Maven with GitHub token uses: ./.github/actions/setupmaven @@ -67,7 +58,7 @@ jobs: uses: actions/checkout@v2 with: path: ${{ env.repoName }} - ref: ${{ env.ref }} + - name: Update utilities path location run: | cd ${{env.repoName}}/weblogic-azure-vm/${{ env.offerName }} diff --git a/.github/workflows/buildWlsVm4CcArtifact.yml b/.github/workflows/buildWlsVm4CcArtifact.yml index e04c36e4e..d8d4a6394 100644 --- a/.github/workflows/buildWlsVm4CcArtifact.yml +++ b/.github/workflows/buildWlsVm4CcArtifact.yml @@ -12,16 +12,14 @@ on: description: 'Specify which pids to use, oracle or microsoft.' required: true default: 'oracle' - ref: - description: 'Specify Git Ref if needed.' - required: false - default: 'refs/heads/main' + # Sample cURL - # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "vms-configured-cluster-package", "client_payload": {"pidType": "microsoft", "ref": "refs/heads/main"} }' + # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "vms-configured-cluster-package", "client_payload": {"pidType": "microsoft"} }' env: offerName: "arm-oraclelinux-wls-cluster" repoName: "weblogic-azure" - repoOwner: ${{ secrets.USER_NAME }} + repoOwner: ${{ github.repository_owner }} + ref: ${{ github.ref_name }} jobs: package: @@ -32,21 +30,16 @@ jobs: run: | if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then pidType=${{ github.event.inputs.pidType }} - ref=${{ github.event.inputs.ref }} else pidType=${{ github.event.client_payload.pidType }} - ref=${{ github.event.client_payload.ref }} fi if [ -z "$pidType" ]; then pidType='microsoft' fi - if [ -z "$ref" ]; then - ref='refs/heads/main' - fi + echo "##[set-output name=pidType;]${pidType}" - echo "##[set-output name=ref;]${ref}" echo "pidType=${pidType}" >> $GITHUB_ENV - echo "ref=${ref}" >> $GITHUB_ENV + - uses: actions/checkout@v2.3.4 - name: Set up Maven with GitHub token uses: ./.github/actions/setupmaven @@ -65,7 +58,7 @@ jobs: uses: actions/checkout@v2 with: path: ${{ env.repoName }} - ref: ${{ env.ref }} + - name: Update utilities path location run: | cd ${{env.repoName}}/weblogic-azure-vm/${{ env.offerName }} diff --git a/.github/workflows/buildWlsVm4DcArtifact.yml b/.github/workflows/buildWlsVm4DcArtifact.yml index f9144bff6..4450d5592 100644 --- a/.github/workflows/buildWlsVm4DcArtifact.yml +++ b/.github/workflows/buildWlsVm4DcArtifact.yml @@ -12,16 +12,14 @@ on: description: 'Specify which pids to use, oracle or microsoft.' required: true default: 'oracle' - ref: - description: 'Specify Git Ref if needed.' - required: false - default: 'refs/heads/main' + # Sample cURL - # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "vms-dynamic-cluster-package", "client_payload": {"pidType": "microsoft", "ref": "refs/heads/main"}}' + # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "vms-dynamic-cluster-package", "client_payload": {"pidType": "microsoft"}}' env: offerName: "arm-oraclelinux-wls-dynamic-cluster" repoName: "weblogic-azure" - repoOwner: ${{ secrets.USER_NAME }} + repoOwner: ${{ github.repository_owner }} + ref: ${{ github.ref_name }} jobs: @@ -33,21 +31,16 @@ jobs: run: | if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then pidType=${{ github.event.inputs.pidType }} - ref=${{ github.event.inputs.ref }} else pidType=${{ github.event.client_payload.pidType }} - ref=${{ github.event.client_payload.ref }} fi if [ -z "$pidType" ]; then pidType='microsoft' fi - if [ -z "$ref" ]; then - ref='refs/heads/main' - fi + echo "##[set-output name=pidType;]${pidType}" - echo "##[set-output name=ref;]${ref}" echo "pidType=${pidType}" >> $GITHUB_ENV - echo "ref=${ref}" >> $GITHUB_ENV + - uses: actions/checkout@v2.3.4 - name: Set up Maven with GitHub token uses: ./.github/actions/setupmaven @@ -62,7 +55,7 @@ jobs: uses: actions/checkout@v2 with: path: ${{ env.repoName }} - ref: ${{ env.ref }} + - name: Update utilities path location run: | cd ${{env.repoName}}/weblogic-azure-vm/${{ env.offerName }} diff --git a/.github/workflows/buildWlsVm4SnArtifact.yml b/.github/workflows/buildWlsVm4SnArtifact.yml index 243824d42..3ce879945 100644 --- a/.github/workflows/buildWlsVm4SnArtifact.yml +++ b/.github/workflows/buildWlsVm4SnArtifact.yml @@ -11,16 +11,14 @@ on: description: 'Specify which pids to use, oracle or microsoft.' required: true default: 'oracle' - ref: - description: 'Specify Git Ref if needed.' - required: false - default: 'refs/heads/main' + # Sample cURL - # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "vms-single-node-package", "client_payload": {"pidType": "microsoft", "ref": "refs/heads/main"}}' + # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "vms-single-node-package", "client_payload": {"pidType": "microsoft"}}' env: offerName: "arm-oraclelinux-wls" repoName: "weblogic-azure" - repoOwner: ${{ secrets.USER_NAME }} + repoOwner: ${{ github.repository_owner }} + ref: ${{ github.ref_name }} jobs: package: @@ -31,24 +29,19 @@ jobs: run: | if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then pidType=${{ github.event.inputs.pidType }} - ref=${{ github.event.inputs.ref }} + else pidType=${{ github.event.client_payload.pidType }} - ref=${{ github.event.client_payload.ref }} + fi if [ -z "$pidType" ]; then pidType='microsoft' fi - if [ -z "$ref" ]; then - ref='refs/heads/main' - fi - echo "##[set-output name=pidType;]${pidType}" - echo "##[set-output name=ref;]${ref}" echo "pidType=${pidType}" >> $GITHUB_ENV - echo "ref=${ref}" >> $GITHUB_ENV + - uses: actions/checkout@v2.3.4 - name: Set up Maven with GitHub token uses: ./.github/actions/setupmaven @@ -63,7 +56,7 @@ jobs: uses: actions/checkout@v2 with: path: ${{ env.repoName }} - ref: ${{ env.ref }} + - name: Build and test ${{ env.offerName }} using ${{ env.pidType }} pids run: | cd ${{env.repoName}}/weblogic-azure-vm/${{ env.offerName }} diff --git a/.github/workflows/it-validation-aks.yaml b/.github/workflows/it-validation-aks.yaml new file mode 100644 index 000000000..1147412bf --- /dev/null +++ b/.github/workflows/it-validation-aks.yaml @@ -0,0 +1,46 @@ +name: IT Validation for AKS +run-name: Running validation workflows with plan:${{ github.event_name == 'schedule' && 'plan-aks' || inputs.it_plan }} + +on: + schedule: + - cron: '0 6 * * 1' # Every Monday at 06:00 UTC + workflow_dispatch: + inputs: + it_plan: + description: 'Path to the validation plan file' + required: true + type: choice + options: + - plan-aks + default: plan-aks + +jobs: + execute-validation: + runs-on: ubuntu-latest + outputs: + results: ${{ steps.it-validation.outputs.results }} + report_url: ${{ steps.it-validation.outputs.report_url }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set validation plan file + id: set-plan-file + run: | + case "${{ inputs.it_plan || 'plan-aks' }}" in + plan-aks) + IT_FILE=".github/it/validation-plan-aks.json" + ;; + *) + echo "Unknown plan option: ${{ inputs.it_plan }}" + exit 1 + ;; + esac + echo "it_file=$IT_FILE" >> $GITHUB_OUTPUT + + - name: Execute IT Validation + id: it-validation + uses: ./.github/actions/it + with: + it_file: ${{ steps.set-plan-file.outputs.it_file }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/it-validation-build.yaml b/.github/workflows/it-validation-build.yaml new file mode 100644 index 000000000..5700d1d7c --- /dev/null +++ b/.github/workflows/it-validation-build.yaml @@ -0,0 +1,46 @@ +name: IT Validation for Build +run-name: Running validation workflows with plan:${{ github.event_name == 'schedule' && 'plan-build' || inputs.it_plan }} + +on: + schedule: + - cron: '0 2 * * *' # Runs daily at 2:00 AM UTC + workflow_dispatch: + inputs: + it_plan: + description: 'Path to the validation plan file' + required: true + type: choice + options: + - plan-build + default: plan-build + +jobs: + execute-validation: + runs-on: ubuntu-latest + outputs: + results: ${{ steps.it-validation.outputs.results }} + report_url: ${{ steps.it-validation.outputs.report_url }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set validation plan file + id: set-plan-file + run: | + case "${{ inputs.it_plan || 'plan-build' }}" in + plan-build) + IT_FILE=".github/it/validation-plan-build.json" + ;; + *) + echo "Unknown plan option: ${{ inputs.it_plan }}" + exit 1 + ;; + esac + echo "it_file=$IT_FILE" >> $GITHUB_OUTPUT + + - name: Execute IT Validation + id: it-validation + uses: ./.github/actions/it + with: + it_file: ${{ steps.set-plan-file.outputs.it_file }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/it-validation-vm-admin.yaml b/.github/workflows/it-validation-vm-admin.yaml new file mode 100644 index 000000000..45eff4ab5 --- /dev/null +++ b/.github/workflows/it-validation-vm-admin.yaml @@ -0,0 +1,46 @@ +name: IT Validation for VM Admin +run-name: Running validation workflows with plan:${{ github.event_name == 'schedule' && 'plan-vm-admin' || inputs.it_plan }} + +on: + schedule: + - cron: '0 1 * * 1' # Every Monday at 01:00 UTC + workflow_dispatch: + inputs: + it_plan: + description: 'Path to the validation plan file' + required: true + type: choice + options: + - plan-vm-admin + default: plan-vm-admin + +jobs: + execute-validation: + runs-on: ubuntu-latest + outputs: + results: ${{ steps.it-validation.outputs.results }} + report_url: ${{ steps.it-validation.outputs.report_url }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set validation plan file + id: set-plan-file + run: | + case "${{ inputs.it_plan || 'plan-vm-admin' }}" in + plan-vm-admin) + IT_FILE=".github/it/validation-plan-vm-admin.json" + ;; + *) + echo "Unknown plan option: ${{ inputs.it_plan }}" + exit 1 + ;; + esac + echo "it_file=$IT_FILE" >> $GITHUB_OUTPUT + + - name: Execute IT Validation + id: it-validation + uses: ./.github/actions/it + with: + it_file: ${{ steps.set-plan-file.outputs.it_file }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/it-validation-vm-cluster.yaml b/.github/workflows/it-validation-vm-cluster.yaml new file mode 100644 index 000000000..86e0820ad --- /dev/null +++ b/.github/workflows/it-validation-vm-cluster.yaml @@ -0,0 +1,46 @@ +name: IT Validation for VM Cluster +run-name: Running validation workflows with plan:${{ github.event_name == 'schedule' && 'plan-vm-cluster' || inputs.it_plan }} + +on: + schedule: + - cron: '0 11 * * 1' # Runs Every Monday at 11:00 UTC + workflow_dispatch: + inputs: + it_plan: + description: 'Path to the validation plan file' + required: true + type: choice + options: + - plan-vm-cluster + default: plan-vm-cluster + +jobs: + execute-validation: + runs-on: ubuntu-latest + outputs: + results: ${{ steps.it-validation.outputs.results }} + report_url: ${{ steps.it-validation.outputs.report_url }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set validation plan file + id: set-plan-file + run: | + case "${{ inputs.it_plan || 'plan-vm-cluster' }}" in + plan-vm-cluster) + IT_FILE=".github/it/validation-plan-vm-cluster.json" + ;; + *) + echo "Unknown plan option: ${{ inputs.it_plan }}" + exit 1 + ;; + esac + echo "it_file=$IT_FILE" >> $GITHUB_OUTPUT + + - name: Execute IT Validation + id: it-validation + uses: ./.github/actions/it + with: + it_file: ${{ steps.set-plan-file.outputs.it_file }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/it-validation-vm-dynamic-cluster.yaml b/.github/workflows/it-validation-vm-dynamic-cluster.yaml new file mode 100644 index 000000000..a7ed8e3c2 --- /dev/null +++ b/.github/workflows/it-validation-vm-dynamic-cluster.yaml @@ -0,0 +1,46 @@ +name: IT Validation for VM Dynamic Cluster +run-name: Running validation workflows with plan:${{ github.event_name == 'schedule' && 'plan-vm-dynamic-cluster' || inputs.it_plan }} + +on: + schedule: + - cron: '0 15 * * 1' # Runs Every Monday at 15:00 UTC + workflow_dispatch: + inputs: + it_plan: + description: 'Path to the validation plan file' + required: true + type: choice + options: + - plan-vm-dynamic-cluster + default: plan-vm-dynamic-cluster + +jobs: + execute-validation: + runs-on: ubuntu-latest + outputs: + results: ${{ steps.it-validation.outputs.results }} + report_url: ${{ steps.it-validation.outputs.report_url }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set validation plan file + id: set-plan-file + run: | + case "${{ inputs.it_plan || 'plan-vm-dynamic-cluster' }}" in + plan-vm-dynamic-cluster) + IT_FILE=".github/it/validation-plan-vm-dynamic-cluster.json" + ;; + *) + echo "Unknown plan option: ${{ inputs.it_plan }}" + exit 1 + ;; + esac + echo "it_file=$IT_FILE" >> $GITHUB_OUTPUT + + - name: Execute IT Validation + id: it-validation + uses: ./.github/actions/it + with: + it_file: ${{ steps.set-plan-file.outputs.it_file }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/newtag.yml b/.github/workflows/newtag.yml index 82a158998..c605d2235 100644 --- a/.github/workflows/newtag.yml +++ b/.github/workflows/newtag.yml @@ -23,7 +23,7 @@ env: repoName: "weblogic-azure" userEmail: ${{ secrets.USER_EMAIL }} userName: ${{ secrets.USER_NAME }} - repoOwner: ${{ secrets.USER_NAME }} + repoOwner: ${{ github.repository_owner }} jobs: newtag: diff --git a/.github/workflows/testWlsAksWithDependencyCreation.yml b/.github/workflows/testWlsAksWithDependencyCreation.yml index 6868151dc..e2a249565 100644 --- a/.github/workflows/testWlsAksWithDependencyCreation.yml +++ b/.github/workflows/testWlsAksWithDependencyCreation.yml @@ -1,4 +1,5 @@ name: Test WLS on AKS with Dependency creation +run-name: Test WLS on AKS with Dependency creation with `db`:${{ inputs.databaseType }} on: workflow_dispatch: @@ -7,14 +8,6 @@ on: description: 'If set to true, resources will not be deleted' required: true default: 'false' - gitUserNameForArtifactsLocation: - description: 'Replaced into https://raw.githubusercontent.com/#gitUserName#/weblogic-azure/#testbranchName#/weblogic-azure-aks/src/main/arm/' - required: true - default: oracle - testBranchNameForArtifactsLocation: - description: 'Replaced into https://raw.githubusercontent.com/#gitUserName#/weblogic-azure/#testbranchName#/weblogic-azure-aks/src/main/arm/' - required: true - default: main vmSize: description: 'The VM size for the AKS pool' required: true @@ -22,9 +15,21 @@ on: location: description: 'The location for the resources' required: true - default: eastus + default: centralus + databaseType: + description: 'Database connection' + required: true + default: 'postgresql(flexible)' + type: choice + options: + - postgresql(flexible) + - postgresql-passwordless(flexible) + configurations_for_it: + description: "JSON string of environment variables used for IT" + required: false + default: '{}' # sample cURL - # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "aks-integration-test-with-dependency-creation", "client_payload": {"gitUserNameForArtifactsLocation": "", "testBranchNameForArtifactsLocation": "", "isForDemo": "false"}}' + # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '{"event_type": "aks-integration-test-with-dependency-creation", "client_payload": {"isForDemo": "false"}}' repository_dispatch: types: [aks-integration-test-with-dependency-creation,integration-test-all] @@ -34,24 +39,24 @@ env: dbAdminUser: weblogic dbPassword: ${{ secrets.DB_PASSWORD }} dbName: wlsdb${{ github.run_id }}${{ github.run_number }} - dbServerName: weblogicdb - ocrSSOPSW: ${{ secrets.ORC_SSOPSW }} + dbServerName: db${{ github.run_id }}${{ github.run_number }} + uamiName: uami${{ github.run_id }}${{ github.run_number }} ocrSSOUser: ${{ secrets.ORC_SSOUSER }} + ocrSSOPSW: ${{ secrets.ORC_SSOPSW }} wdtRuntimePassword: ${{ secrets.WDT_RUNTIMEPSW}} wlsUserName: ${{ secrets.WLS_USERNAME }} wlsPassword: ${{ secrets.WLS_PSW }} - resourceGroupForDB: wlsd-db-${{ github.run_id }}-${{ github.run_number }} + resourceGroupForDB: wlsd-db-${{ github.repository_owner }}-${{ 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 }} + wlsImageTag: "14.1.2.0-generic-jdk17-ol9" jobs: preflight: outputs: artifactName: ${{steps.artifact_file.outputs.artifactName}} isForDemo: ${{ steps.setup-env-variables-based-on-dispatch-event.outputs.isForDemo }} - gitUserNameForArtifactsLocation: ${{ steps.setup-env-variables-based-on-dispatch-event.outputs.gitUserNameForArtifactsLocation }} - testBranchNameForArtifactsLocation: ${{ steps.setup-env-variables-based-on-dispatch-event.outputs.testBranchNameForArtifactsLocation }} azCliVersion: ${{steps.set-az-cli-version.outputs.azCliVersion}} vmSize: ${{ steps.setup-env-variables-based-on-dispatch-event.outputs.vmSize }} location: ${{ steps.setup-env-variables-based-on-dispatch-event.outputs.location }} @@ -76,30 +81,22 @@ jobs: - name: Setup environment variables id: setup-env-variables-based-on-dispatch-event run: | - location=eastus # default value + location=centralus # default value if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then isForDemo=${{ github.event.inputs.isForDemo }} - gitUserNameForArtifactsLocation=${{ github.event.inputs.gitUserNameForArtifactsLocation }} - testBranchNameForArtifactsLocation=${{ github.event.inputs.testBranchNameForArtifactsLocation }} vmSize=${{ github.event.inputs.vmSize }} location=${{ github.event.inputs.location }} else isForDemo=${{ github.event.client_payload.isForDemo }} - gitUserNameForArtifactsLocation=${{ github.event.client_payload.gitUserNameForArtifactsLocation }} - testBranchNameForArtifactsLocation=${{ github.event.client_payload.testBranchNameForArtifactsLocation }} vmSize=${{ github.event.client_payload.vmSize }} location=${{ github.event.client_payload.location }} fi echo "##[set-output name=isForDemo;]${isForDemo}" - echo "##[set-output name=gitUserNameForArtifactsLocation;]${gitUserNameForArtifactsLocation}" - echo "##[set-output name=testBranchNameForArtifactsLocation;]${testBranchNameForArtifactsLocation}" echo "##[set-output name=vmSize;]${vmSize}" echo "##[set-output name=location;]${location}" echo "isForDemo=${isForDemo}" >> $GITHUB_ENV - echo "gitUserNameForArtifactsLocation=${gitUserNameForArtifactsLocation}" >> $GITHUB_ENV - echo "testBranchNameForArtifactsLocation=${testBranchNameForArtifactsLocation}" >> $GITHUB_ENV echo "vmSize=${vmSize}" >> $GITHUB_ENV echo "location=${location}" >> $GITHUB_ENV - uses: actions/checkout@v2.3.4 @@ -139,37 +136,7 @@ jobs: with: name: ${{steps.artifact_file.outputs.artifactName}} path: ${{steps.artifact_file.outputs.artifactPath}} - deploy-db: - needs: preflight - runs-on: ubuntu-latest - steps: - - name: Get AZ CLI Version - run: | - echo "azCliVersion=${{needs.preflight.outputs.azCliVersion}}" >> $GITHUB_ENV - 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 - - uses: actions/checkout@v2.3.4 - - name: Set up PostgreSQL Flexible Server that allows access from Azure services - uses: ./.github/actions/createPostgresqlFlexibleServer - with: - dbAdminUser: ${{ env.dbAdminUser }} - dbName: ${{ env.dbName }} - dbPassword: ${{ env.dbPassword }} - dbServerName: ${{ env.dbServerName }} - location: $location - resourceGroupName: ${{ env.resourceGroupForDB }} - deploy-storage-account: needs: preflight runs-on: ubuntu-latest @@ -228,15 +195,16 @@ jobs: inlineScript: | az storage blob upload --account-name ${{ env.storageAccountName }} --container-name ${{ env.storageContainerName }} --file cargotracker/target/cargo-tracker.war --name cargo-tracker.war deploy-wls-on-aks: - needs: [deploy-storage-account, deploy-db, preflight] + needs: [deploy-storage-account, preflight] runs-on: ubuntu-latest + env: ${{ fromJson(inputs.configurations_for_it) }} steps: - name: Get AZ CLI Version run: | echo "azCliVersion=${{needs.preflight.outputs.azCliVersion}}" >> $GITHUB_ENV echo "location=${{needs.preflight.outputs.location}}" >> $GITHUB_ENV - name: Checkout weblogic-azure - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: weblogic-azure - name: Download artifact for deployment @@ -281,24 +249,130 @@ jobs: with: repository: Azure-Samples/cargotracker-wls-aks path: cargotracker + + - name: Provision Azure Vnet + id: vnet-provision + if: ${{ env.newOrExistingVnetForApplicationGateway == 'existing' }} + run: | + echo "Provisioning Azure Vnet with subnet" + az network vnet create \ + --resource-group ${{ env.resourceGroupForWlsAks }} \ + --name ${{ env.vnetForApplicationGateway.name }} \ + --address-prefix 10.0.0.0/28 \ + --subnet-name ${{ env.vnetForApplicationGateway.subnets.gatewaySubnet.name }} \ + --subnet-prefix 10.0.0.0/29 + + - name: Create Database Resource Group + uses: azure/CLI@v1 + with: + azcliversion: ${{ env.azCliVersion }} + inlineScript: | + echo "create database resource group" ${{ env.resourceGroupForDB }} + az group create --verbose --name ${{ env.resourceGroupForDB }} --location $location + + - name: Provision database + id: database-provision + uses: ./weblogic-azure/.github/actions/database-provision + with: + databaseType: ${{ inputs.databaseType }} + resourceGroup: ${{ env.resourceGroupForDB }} + uamiName: ${{ env.uamiName }} + location: $location + dbInstanceName: ${{ env.dbServerName }} + dbPassword: ${{ env.dbPassword }} + databaseName: ${{ env.dbName }} + dbAdminUser: ${{ env.dbAdminUser }} + + - name: Get database parameters + id: database-parameters + uses: ./weblogic-azure/.github/actions/database-parameters + with: + databaseType: ${{ inputs.databaseType }} + uamiId: ${{ steps.database-provision.outputs.uamiId }} + serverHost: ${{ steps.database-provision.outputs.serverHost }} + dbInstanceName: ${{ env.dbServerName }} + databaseName: ${{ env.dbName }} + dbAdminUser: ${{ env.dbAdminUser }} + - name: Prepare parameter file run: | + if ${{ env.createAKSCluster == 'false' }}; then + echo "Deploy with an existing AKS cluster" + export createAKSCluster=false + # the env aksClusterName is set in the `validation-plan-aks.json` file. + export aksClusterName=${{ env.aksClusterName }} + export aksClusterRGName=${{ env.resourceGroupForWlsAks }} + else + echo "Deploy with a new AKS cluster" + export createAKSCluster=true + export aksClusterName="aks-cluster-${{ github.run_id }}-${{ github.run_number }}" + export aksClusterRGName=${{ env.resourceGroupForWlsAks }} + fi + + if ${{ env.enableAppGWIngress == 'false' }}; then + echo "Application Gateway Ingress Controller is disabled" + export enableAppGWIngress=false + else + echo "Application Gateway Ingress Controller is enabled" + export enableAppGWIngress=true + fi + + # prepare parameters for vnet and application gateway + export newOrExistingVnetForApplicationGateway=${{ env.newOrExistingVnetForApplicationGateway }} + export vnetForApplicationGateway=${{ env.vnetForApplicationGateway.name }} + export vnetRGNameForApplicationGateway=${{ env.resourceGroupForWlsAks }} + echo "generate parameter file" - bash weblogic-azure/weblogic-azure-aks/src/test/genWlsAksParameters.sh \ - ${{ needs.preflight.outputs.gitUserNameForArtifactsLocation }} \ - ${{ needs.preflight.outputs.testBranchNameForArtifactsLocation }} \ - "${cargoTrackerBlobUrl}" \ - ${dbPassword} \ - ${dbAdminUser} \ - jdbc:postgresql:\/\/${dbName}.postgres.database.azure.com:5432\/${{ env.dbServerName }} \ - ${location} \ - ${ocrSSOPSW} \ - ${ocrSSOUser} \ - ${wdtRuntimePassword} \ - ${wlsPassword} \ - ${wlsUserName} \ - ${{ needs.preflight.outputs.vmSize }} \ - weblogic-azure/weblogic-azure-aks/src/test/setupWlsAksParameters.jsonc + export databaseType='${{ steps.database-parameters.outputs.databaseType }}' + export enableDB=${{ steps.database-parameters.outputs.enableDB }} + export enablePswlessConnection=${{ steps.database-parameters.outputs.enablePswlessConnection }} + export dsConnectionURL='${{ steps.database-parameters.outputs.dsConnectionURL }}' + export dbUser='${{ steps.database-parameters.outputs.dbUser }}' + export dbIdentity='${{ steps.database-parameters.outputs.dbIdentity }}' + export dbPassword=${{ env.dbPassword }} + export wlsImageTag=${{ env.wlsImageTag }} + + export gitUserName=${{ github.repository_owner }} + export testbranchName=${{ github.sha }} + export appPackageUrls=${cargoTrackerBlobUrl} + + export location=${location} + export ocrSSOPSW=${ocrSSOPSW} + export ocrSSOUser=${ocrSSOUser} + export wdtRuntimePassword=${wdtRuntimePassword} + export wlsPassword=${wlsPassword} + export wlsUserName=${wlsUserName} + export vmSize=${{ needs.preflight.outputs.vmSize }} + + echo "Generating parameter file..." + envsubst < "./weblogic-azure/weblogic-azure-aks/src/test/parameters-deploy-template.json" > "./weblogic-azure/weblogic-azure-aks/src/test/parameters-deploy-${{ github.job }}.json" + + - name: Archive parameters-deploy.json + uses: actions/upload-artifact@v4.6.2 + if: success() + with: + name: parameters-deploy.json + path: ./weblogic-azure/weblogic-azure-aks/src/test/parameters-deploy-${{ github.job }}.json + + - name: Provision AKS Cluster as an existing cluster for deployment + if: ${{ env.createAKSCluster == 'false' }} + run: | + # the value of **createAKSCluster** is `false`, which means the offer won't create a new AKS cluster, but use an existing one. + # in order to simulate the same behavior as the offer, we need to create a new AKS cluster. + + az feature register \ + --namespace "Microsoft.ContainerService" \ + --name "AppGatewayWithOverlayPreview" + az provider register --namespace Microsoft.ContainerService + + az aks create \ + -n ${{ env.aksClusterName }} \ + -g ${{ env.resourceGroupForWlsAks }} \ + --enable-managed-identity \ + --network-plugin azure \ + --load-balancer-sku standard \ + --generate-ssh-keys + - name: Deploy WebLogic Server Cluster Domain offer id: deploy-wls-cluster uses: azure/CLI@v1 @@ -310,10 +384,17 @@ jobs: --verbose \ --resource-group ${{ env.resourceGroupForWlsAks }} \ --name wls-on-aks \ - --parameters @weblogic-azure/weblogic-azure-aks/src/test/setupWlsAksParameters.jsonc \ + --parameters @weblogic-azure/weblogic-azure-aks/src/test/parameters-deploy-${{ github.job }}.json \ --template-file ${artifactName}/mainTemplate.json + + - name: Query Application Gateway URL run: | + if ${{ env.enableAppGWIngress == 'false' }}; then + echo skipping current step as Application Gateway Ingress Controller is disabled + exit 0 + fi + appgatewayname=$(az resource list --resource-group ${{ env.resourceGroupForWlsAks }} --query "[?type=='Microsoft.Network/applicationGateways'].name|[0]" -o tsv) echo $appgatewayname publicIpAddressId=$(az network application-gateway show --resource-group ${{ env.resourceGroupForWlsAks }} --name ${appgatewayname} --query frontendIPConfigurations[0].publicIPAddress.id -o tsv) @@ -323,6 +404,11 @@ jobs: echo "appGatewayURL=${appGatewayURL}" >> $GITHUB_ENV - name: Verify Cargo Tracker is deployed as expected run: | + if ${{ env.enableAppGWIngress == 'false' }}; then + echo skipping current step as Application Gateway Ingress Controller is disabled + exit 0 + fi + echo "Verifying Cargo Tracker is deployed as expected" curl --verbose http://${{ env.appGatewayURL }}/cargo-tracker/ response=$(curl --write-out '%{http_code}' --silent --output /dev/null http://${{ env.appGatewayURL }}/cargo-tracker/) @@ -428,7 +514,7 @@ jobs: fi cleanup: needs: [deploy-wls-on-aks, preflight] - if: ${{ needs.preflight.outputs.isForDemo == 'false' }} + if: ${{ always() && needs.preflight.outputs.isForDemo == 'false' }} runs-on: ubuntu-latest steps: - name: Get AZ CLI Version diff --git a/.github/workflows/testWlsAksWithoutDependencyCreation.yml b/.github/workflows/testWlsAksWithoutDependencyCreation.yml index d03b85ff6..5c9df73dc 100644 --- a/.github/workflows/testWlsAksWithoutDependencyCreation.yml +++ b/.github/workflows/testWlsAksWithoutDependencyCreation.yml @@ -15,9 +15,6 @@ on: description: 'If set to true, resources will not be deleted' required: true default: 'false' - disambiguationSuffix: - description: 'Included in names to disambiguate. Get from another pipeline execution' - required: true storageAccountName: description: 'Specify storage account of uploading .war file' required: true @@ -34,7 +31,7 @@ on: # sample cURL # curl --verbose -X POST https://api.github.com/repos//weblogic-azure/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -H 'Authorization: token ' --data '' # sample - # {"event_type": "aks-integration-test-without-dependency-creation", "client_payload": {"gitUserNameForArtifactsLocation": "", "testBranchNameForArtifactsLocation": "", "isForDemo": "false", "disambiguationSuffix": "1397121054", "storageAccountName": "wlsdsa13971210545", "storageContainerName": "wlsdcon13971210545", "dbName": "wlsdb13971210545"}} + # {"event_type": "aks-integration-test-without-dependency-creation", "client_payload": {"gitUserNameForArtifactsLocation": "", "testBranchNameForArtifactsLocation": "", "isForDemo": "false", "storageAccountName": "wlsdsa13971210545", "storageContainerName": "wlsdcon13971210545", "dbName": "wlsdb13971210545"}} # the request data can be get from setupWlsAksDependency pipeline, please checkout the summary page and download the generated artifact name 'integration-test-data' repository_dispatch: types: [aks-integration-test-without-dependency-creation,integration-test-all] @@ -86,7 +83,7 @@ jobs: id: setup-env-variables-based-on-dispatch-event run: | if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then - resourceGroupForWlsAks=wlsd-aks-${{ github.event.inputs.disambiguationSuffix }}-${{ github.run_number }} + resourceGroupForWlsAks=wlsd-aks-${{ github.repository_owner }}-${{ github.run_id }}-${{ github.run_number }} dbName=${{ github.event.inputs.dbName }} storageAccountName=${{ github.event.inputs.storageAccountName }} storageContainerName=${{ github.event.inputs.storageContainerName }} @@ -95,7 +92,7 @@ jobs: testBranchNameForArtifactsLocation=${{ github.event.inputs.testBranchNameForArtifactsLocation }} vmSize=${{ github.event.inputs.vmSize }} else - resourceGroupForWlsAks=wlsd-aks-${{ github.event.client_payload.disambiguationSuffix }}-${{ github.run_number }} + resourceGroupForWlsAks=wlsd-aks-${{ github.repository_owner }}-${{ github.run_id }}-${{ github.run_number }} dbName=${{ github.event.client_payload.dbName }} storageAccountName=${{ github.event.client_payload.storageAccountName }} storageContainerName=${{ github.event.client_payload.storageContainerName }} diff --git a/.github/workflows/testWlsVmAdmin.yml b/.github/workflows/testWlsVmAdmin.yml index 45362f17d..ebd99dbba 100644 --- a/.github/workflows/testWlsVmAdmin.yml +++ b/.github/workflows/testWlsVmAdmin.yml @@ -2,18 +2,31 @@ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. name: Test Admin Server on VM +run-name: Test Admin Server on VM with `db`:${{ inputs.databaseType }} on: workflow_dispatch: inputs: - ref: - description: 'Specify Git Ref if needed.' - required: false - default: 'refs/heads/main' location: description: 'The location for the resources' required: true - default: eastus + default: centralus + databaseType: + description: 'Database connection' + required: true + default: 'mssqlserver' + type: choice + options: + - none + - mssqlserver + - mssqlserver-passwordless + - postgresql(flexible) + - postgresql-passwordless(flexible) + configurations_for_it: + description: "JSON string of environment variables used for IT" + required: false + default: '{}' + # Allows you to run this workflow using GitHub APIs # PERSONAL_ACCESS_TOKEN= # REPO_NAME=mriccell/weblogic-azure @@ -27,20 +40,35 @@ env: adminPassword: ${{ secrets.WLS_PSW }} dbAdminUser: weblogic dbName: wlsdb${{ github.run_id }}${{ github.run_number }} - dbServerName: weblogicdb + dbServerName: weblogicdb-${{ github.run_id }}-${{ github.run_number }} + uamiName: uami${{ github.run_id }}${{ github.run_number }} gitToken: ${{ secrets.GIT_TOKEN }} offerName: arm-oraclelinux-wls-admin - adminOfferPath: weblogic-azure/weblogic-azure-vm/arm-oraclelinux-wls-admin + offerPath: weblogic-azure/weblogic-azure-vm/arm-oraclelinux-wls-admin testbranchName: cicd-${{ github.run_id }}-${{ github.run_number }} repoName: weblogic-azure - repoOwner: ${{ secrets.USER_NAME }} - resourceGroupPrefix: wls-${{ github.run_id }}-${{ github.run_number }} - resourceGroupForDependency: wlsd-${{ github.run_id }}-${{ github.run_number }} + repoOwner: ${{ github.repository_owner }} + resourceGroupPrefix: wls-${{ github.repository_owner }}-${{ github.run_id }}-${{ github.run_number }} + resourceGroupForDependency: wlsd-${{ github.repository_owner }}-${{ github.run_id }}-${{ github.run_number }} userEmail: ${{ secrets.USER_EMAIL }} userName: ${{ secrets.USER_NAME }} wlsPassword: ${{ secrets.WLS_PSW }} wlsDomainName: adminDomain wlsUserName: weblogic + ref: ${{ github.ref_name }} + images: | + owls-141100-jdk11-ol91;Oracle:weblogic-141100-jdk11-ol91:owls-141100-jdk11-ol91;latest + owls-141100-jdk11-ol87;Oracle:weblogic-141100-jdk11-ol87:owls-141100-jdk11-ol87;latest + owls-141100-jdk8-ol91;Oracle:weblogic-141100-jdk8-ol91:owls-141100-jdk8-ol91;latest + owls-141100-jdk8-ol87;Oracle:weblogic-141100-jdk8-ol87:owls-141100-jdk8-ol87;latest + owls-122140-jdk8-ol91;Oracle:weblogic-122140-jdk8-ol91:owls-122140-jdk8-ol91;latest + owls-122140-jdk8-ol87;Oracle:weblogic-122140-jdk8-ol87:owls-122140-jdk8-ol87;latest + owls-122140-jdk8-ol76;Oracle:weblogic-122140-jdk8-ol76:owls-122140-jdk8-ol7;latest + owls-141100-jdk8-ol76;Oracle:weblogic-141100-jdk8-ol76:owls-141100-jdk8-ol7;latest + owls-141100-jdk11-ol76;Oracle:weblogic-141100-jdk11-ol76:owls-141100-jdk11-ol7;latest + owls-122140-jdk8-rhel76;Oracle:weblogic-122140-jdk8-rhel76:owls-122140-jdk8-rhel76;latest + owls-141100-jdk8-rhel76;Oracle:weblogic-141100-jdk8-rhel76:owls-141100-jdk8-rhel76;latest + owls-141100-jdk11-rhel76;Oracle:weblogic-141100-jdk11-rhel76:owls-141100-jdk11-rhel76;latest jobs: preflight: @@ -55,20 +83,12 @@ jobs: location=eastus # default value if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then - ref=${{ github.event.inputs.ref }} location=${{ github.event.inputs.location }} else - ref=${{ github.event.client_payload.ref }} location=${{ github.event.client_payload.location }} fi - if [ -z "$ref" ]; then - ref='refs/heads/main' - fi - - echo "##[set-output name=ref;]${ref}" echo "##[set-output name=location;]${location}" - echo "ref=${ref}" >> $GITHUB_ENV echo "location=${location}" >> $GITHUB_ENV - uses: actions/checkout@v2.3.4 - name: Set up Maven with GitHub token @@ -90,12 +110,11 @@ jobs: uses: actions/checkout@v2 with: repository: ${{env.repoOwner}}/${{env.repoName}} - ref: ${{ env.ref }} path: ${{env.repoName}} - name: Build and test ${{ env.offerName }} run: | ls - mvn -Ptemplate-validation-tests clean install -Dgit.repo.owner=${{ env.repoOwner }} -Dgit.tag=${{ env.ref }} --file ${adminOfferPath}/pom.xml + mvn -Ptemplate-validation-tests clean install -Dgit.repo.owner=${{ env.repoOwner }} -Dgit.tag=${{ env.ref }} --file ${offerPath}/pom.xml - name: Checkout ${{env.repoOwner}}/${{env.repoName}} for test uses: actions/checkout@v2 @@ -114,7 +133,7 @@ jobs: echo "create branch $testbranchName" git checkout -b $testbranchName rm -r -f $current/${offerDevPath}/src/main/arm/nestedtemplates/* - cp -r -f $current/${{ env.adminOfferPath }}/target/arm/nestedtemplates/* $current/${offerDevPath}/src/main/arm/nestedtemplates/ + cp -r -f $current/${{ env.offerPath }}/target/arm/nestedtemplates/* $current/${offerDevPath}/src/main/arm/nestedtemplates/ git status git commit -a -m "hard code pids" git push https://$gitToken@github.com/${GITHUB_REPOSITORY}.git -f @@ -126,10 +145,10 @@ jobs: - name: Validate deployment templates for different combinations of service integration id: validate-deployment-templates run: | - bash ${{ env.adminOfferPath }}/test/scripts/verify-deployments.sh \ + bash ${{ env.offerPath }}/test/scripts/verify-deployments.sh \ <<< "${{ github.run_id }}${{ github.run_number }} ${location} \ - ${{ env.adminOfferPath }}/target/arm/mainTemplate.json \ - ${GITHUB_REPOSITORY} ${testbranchName} ${{ env.adminOfferPath }}/test/scripts" + ${{ env.offerPath }}/target/arm/mainTemplate.json \ + ${GITHUB_REPOSITORY} ${testbranchName} ${{ env.offerPath }}/test/scripts" - name: Get version information from pom.xml id: version @@ -147,13 +166,13 @@ jobs: run: echo "##[set-output name=artifactName;]${{ env.offerName }}-$version-arm-assembly" - name: Generate zip package path id: artifact_path - run: echo "##[set-output name=artifactPath;]${{ env.adminOfferPath }}/target/$artifactName" + run: echo "##[set-output name=artifactPath;]${{ env.offerPath }}/target/$artifactName" - name: Output artifact path run: echo $artifactPath env: artifactPath: ${{steps.package.outputs.artifactPath}} - name: Unzip the package as upload action will zip again - run: unzip ${{ env.adminOfferPath }}/target/$artifactName.zip -d ${{ env.adminOfferPath }}/target/$artifactName + run: unzip ${{ env.offerPath }}/target/$artifactName.zip -d ${{ env.offerPath }}/target/$artifactName - name: Archive ${{ env.offerName }} template uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 @@ -179,49 +198,22 @@ jobs: echo "create resource group" ${{ env.resourceGroupForDependency }} az group create --verbose --name ${{ env.resourceGroupForDependency }} --location ${location} - uses: actions/checkout@v2.3.4 - - name: Set up PostgreSQL Flexible Server that allows access from Azure services - uses: ./.github/actions/createPostgresqlFlexibleServer - with: - dbAdminUser: ${{ env.dbAdminUser }} - dbName: ${{ env.dbName }} - dbPassword: ${{ env.wlsPassword }} - dbServerName: ${{ env.dbServerName }} - location: ${{ env.location }} - resourceGroupName: ${{ env.resourceGroupForDependency }} deploy-weblogic-admin: needs: [deploy-dependencies, preflight] runs-on: ubuntu-latest - strategy: - max-parallel: 1 - fail-fast: false - matrix: - images: - [ - "owls-141100-jdk11-ol91;Oracle:weblogic-141100-jdk11-ol91:owls-141100-jdk11-ol91;latest", - "owls-141100-jdk11-ol87;Oracle:weblogic-141100-jdk11-ol87:owls-141100-jdk11-ol87;latest", - "owls-141100-jdk8-ol91;Oracle:weblogic-141100-jdk8-ol91:owls-141100-jdk8-ol91;latest", - "owls-141100-jdk8-ol87;Oracle:weblogic-141100-jdk8-ol87:owls-141100-jdk8-ol87;latest", - "owls-122140-jdk8-ol91;Oracle:weblogic-122140-jdk8-ol91:owls-122140-jdk8-ol91;latest", - "owls-122140-jdk8-ol87;Oracle:weblogic-122140-jdk8-ol87:owls-122140-jdk8-ol87;latest", - "owls-122140-jdk8-ol76;Oracle:weblogic-122140-jdk8-ol76:owls-122140-jdk8-ol7;latest", - "owls-141100-jdk8-ol76;Oracle:weblogic-141100-jdk8-ol76:owls-141100-jdk8-ol7;latest", - "owls-141100-jdk11-ol76;Oracle:weblogic-141100-jdk11-ol76:owls-141100-jdk11-ol7;latest", - "owls-122140-jdk8-rhel76;Oracle:weblogic-122140-jdk8-rhel76:owls-122140-jdk8-rhel76;latest", - "owls-141100-jdk8-rhel76;Oracle:weblogic-141100-jdk8-rhel76:owls-141100-jdk8-rhel76;latest", - "owls-141100-jdk11-rhel76;Oracle:weblogic-141100-jdk11-rhel76:owls-141100-jdk11-rhel76;latest" - ] - + env: ${{ fromJson(inputs.configurations_for_it) }} steps: - name: Initialize environment variables run: | echo "location=${{needs.preflight.outputs.location}}" >> $GITHUB_ENV echo "artifactName=${{ needs.preflight.outputs.artifactName }}" >> $GITHUB_ENV - - name: Checkout ${{env.repoOwner}}/${{env.repoName}} - uses: actions/checkout@v2 + + - name: Checkout weblogic-azure repository + uses: actions/checkout@v4 with: - repository: ${{env.repoOwner}}/${{env.repoName}} path: ${{env.repoName}} + - name: Download artifact for deployment uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: @@ -232,120 +224,203 @@ jobs: id: azure-login with: creds: ${{ secrets.AZURE_CREDENTIALS }} - - name: Get Image SKU - id: image-sku - run: | - imageUrn="${{ matrix.images }}" - sku=${imageUrn%%;*} - echo "sku=${sku}" >> $GITHUB_ENV - echo ${resourceGroupPrefix} - resourceGroup=$(echo "${resourceGroupPrefix}-${sku}" | sed "s/_//g") - echo "resourceGroup=${resourceGroup}" >> $GITHUB_ENV - - name: Create Resource Group - id: create-resource-group - run: | - echo "create resource group" $resourceGroup - az group create --verbose --name $resourceGroup --location ${location} - echo "resourceGroup=${resourceGroup}" >> $GITHUB_ENV - - name: Prepare deployed parameters and test script - id: prepare-deployed-parameters-and-test-script - run: | - repoPath=${GITHUB_REPOSITORY//\//\\/} - # Generate parameters for db template deployment - bash ${{ env.adminOfferPath }}/test/scripts/gen-parameters-deploy.sh \ - <<< "${{ env.adminOfferPath }}/test/scripts/ \ - $wlsPassword \ - ${{ matrix.images }} \ - $wlsDomainName \ - ${{ env.adminVMName }} \ - ${{ env.wlsPassword}} \ - ${{ env.dbAdminUser }} \ - ${{ env.dbName }} \ - ${{ env.location }} \ - ${{ env.wlsUserName }} \ - ${{ env.wlsPassword }} \ - ${GITHUB_REPOSITORY} \ - ${{ env.testbranchName }}" + - name: Provision database + id: database-provision + uses: ./weblogic-azure/.github/actions/database-provision + with: + databaseType: ${{ inputs.databaseType }} + resourceGroup: ${{ env.resourceGroupForDependency }} + uamiName: ${{ env.uamiName }} + location: ${{ env.location }} + dbInstanceName: ${{ env.dbServerName }} + dbPassword: ${{ env.wlsPassword }} + databaseName: ${{ env.dbName }} + dbAdminUser: ${{ env.dbAdminUser }} - - name: Accept Image Terms - id: accept-terms - run: | - echo "accept terms for " "${{ matrix.images }}" - rawUrn="${{ matrix.images }}" - publisherAndName=$(echo ${rawUrn} | grep -o ";.*:" | sed "s/;//g") - imageVersion=${rawUrn##*;} - az vm image terms accept --urn ${publisherAndName}${sku}:${imageVersion} + - name: Get database parameters + id: database-parameters + uses: ./weblogic-azure/.github/actions/database-parameters + with: + databaseType: ${{ inputs.databaseType }} + uamiId: ${{ steps.database-provision.outputs.uamiId }} + serverHost: ${{ steps.database-provision.outputs.serverHost }} + dbInstanceName: ${{ env.dbServerName }} + databaseName: ${{ env.dbName }} + dbAdminUser: ${{ env.dbAdminUser }} - - name: Deploy WebLogic Server Admin only Domain offer - id: deploy-wls-admin + - name: Provision Azure Vnet + id: vnet-provision + if: ${{ env.virtualNetworkNewOrExisting == 'existing' }} run: | - az deployment group create \ - --verbose \ - --resource-group $resourceGroup \ - --name wls-admin-node \ - --parameters @${{ env.adminOfferPath }}/test/scripts/parameters-deploy.json \ - --template-file ${artifactName}/mainTemplate.json + echo "Provisioning Azure Vnet with subnet" + az network vnet create \ + --resource-group ${{ env.resourceGroupForDependency }} \ + --name ${{ env.virtualNetworkName }} \ + --address-prefix 10.0.0.0/28 \ + --subnet-name ${{ env.subnetName }} \ + --subnet-prefix 10.0.0.0/29 - # query the admin vm name - export adminVMName=$(az deployment group show \ - --resource-group $resourceGroup \ - --name wls-admin-node \ - --query "properties.outputs.adminVMName.value" -o tsv) - echo "adminVMName=${adminVMName}" >> $GITHUB_ENV - - - name: Verify system services at admin server - id: veriy-admin-service + - name: Try each image until one succeeds run: | - echo "Verifying WebLogic services at admin server" - message=$(az vm run-command invoke \ - --resource-group $resourceGroup \ - --name $adminVMName \ - --command-id RunShellScript \ - --scripts @${{ env.adminOfferPath }}/test/scripts/verify-services.sh \ - --query value[*].message) + # Convert multiline string to array + IFS=$'\n' read -d '' -r -a image_array <<< "${{ env.images }}" || true + + success=false + + for image in "${image_array[@]}"; do + if [ -z "$image" ]; then + continue + fi + + echo "::group::Trying image: $image" + + # Set deployment variables for this image + imageUrn="$image" + sku=${imageUrn%%;*} + resourceGroup=$(echo "${resourceGroupPrefix}-${sku}" | sed "s/_//g") + + echo "Deploying with SKU: $sku" + echo "Resource Group: $resourceGroup" + + # Export db variables for envsubst + export databaseType='${{ steps.database-parameters.outputs.databaseType }}' + export enableDB=${{ steps.database-parameters.outputs.enableDB }} + export enablePswlessConnection=${{ steps.database-parameters.outputs.enablePswlessConnection }} + export dsConnectionURL='${{ steps.database-parameters.outputs.dsConnectionURL }}' + export dbUser='${{ steps.database-parameters.outputs.dbUser }}' + export dbIdentity='${{ steps.database-parameters.outputs.dbIdentity }}' + export dbPassword='${{ env.wlsPassword}}' + export dbName='${{ env.dbName }}' - if [[ $message == *"not in active (running) state"* ]]; then - echo "Error: $message" + # Try deployment with this image + if bash -c " + set -e + + # Create Resource Group + echo 'Creating resource group: $resourceGroup' + az group create --verbose --name '$resourceGroup' --location '${location}' + + ## Prepare Vnet parameters + if [ "${{ env.virtualNetworkNewOrExisting }}" == "existing" ]; then + export virtualNetworkResourceGroupName=${{ env.resourceGroupForDependency }} + export virtualNetworkNewOrExisting=${{ env.virtualNetworkNewOrExisting }} + export virtualNetworkName=${{ env.virtualNetworkName }} + export subnetName=${{ env.subnetName }} + else + export virtualNetworkResourceGroupName='$resourceGroup' + export virtualNetworkNewOrExisting="new" + export virtualNetworkName="wls-vnet" + export subnetName="wls-subnet" + fi + + # Export variables for envsubst + export adminPasswordOrKey='${{ env.wlsPassword }}' + export skuUrnVersion='$image' + export wlsdomainname='${{ env.wlsDomainName }}' + export adminVMName='${{ env.adminVMName }}' + export location='${{ env.location }}' + export wlsusername='${{ env.wlsUserName }}' + export wlspassword='${{ env.wlsPassword }}' + export repoPath='${GITHUB_REPOSITORY}' + export testbranchName='${{ env.testbranchName }}' + + echo 'Generating parameter file...' + envsubst < './${{ env.offerPath }}/test/scripts/parameters-deploy-template.json' > './${{ env.offerPath }}/test/parameters-deploy-${{ github.job }}.json' + + # Accept Image Terms + echo 'Accepting terms for image: $image' + rawUrn='$image' + publisherAndName=\$(echo \${rawUrn} | grep -o ';.*:' | sed 's/;//g') + imageVersion=\${rawUrn##*;} + az vm image terms accept --urn \${publisherAndName}$sku:\${imageVersion} + + # Deploy WebLogic Server + echo 'Deploying WebLogic Server...' + az deployment group create \ + --verbose \ + --resource-group '$resourceGroup' \ + --name wls-admin-node \ + --parameters @'./${{ env.offerPath }}/test/parameters-deploy-${{ github.job }}.json' \ + --template-file '${{needs.preflight.outputs.artifactName}}/mainTemplate.json' + + # Get admin VM name + adminVMName=\$(az deployment group show \ + --resource-group '$resourceGroup' \ + --name wls-admin-node \ + --query 'properties.outputs.adminVMName.value' -o tsv) + + # Verify system services + echo 'Verifying WebLogic services...' + message=\$(az vm run-command invoke \ + --resource-group '$resourceGroup' \ + --name \$adminVMName \ + --command-id RunShellScript \ + --scripts @'${{ env.offerPath }}/test/scripts/verify-services.sh' \ + --query value[*].message) + + if [[ \$message == *'not in active (running) state'* ]]; then + echo 'Error: \$message' + exit 1 + fi + + if [ "${{ env.virtualNetworkNewOrExisting }}" == "existing" ]; then + # If using existing VNet, there are some gaps to verify the deployment using following steps. + echo 'skip following steps, only verify the deployment for existing vnet' + exit 0 + fi + + # Configure network security group + echo 'Configuring network security group...' + nsg=\$(az network nsg list \ + --resource-group '$resourceGroup' \ + --query '[0].name' -o tsv) + + az network nsg rule update \ + --resource-group '$resourceGroup' \ + --nsg-name \${nsg} \ + --name WebLogicAdminChannelPort \ + --access Allow \ + --source-address-prefixes 10.0.0.0/24 + + # Get public IP + publicIP=\$(az vm show \ + --resource-group '$resourceGroup' \ + --name \$adminVMName -d \ + --query publicIps -o tsv) + + # Verify WebLogic Server Access + echo 'Verifying WebLogic Server Access...' + bash '${{ env.offerPath }}/test/scripts/verify-wls-access.sh' <<< \"\${publicIP} ${adminConsolePort}\" + + echo 'SUCCESS: All verification steps passed!' + exit 0 + "; then + echo "✅ SUCCESS: WebLogic deployment succeeded with image: $image" + echo "successful_image=$image" >> $GITHUB_ENV + echo "successful_resource_group=$resourceGroup" >> $GITHUB_ENV + success=true + + # Clean up successful deployment + echo "Cleaning up resource group: $resourceGroup" + az group delete --yes --no-wait --verbose --name "$resourceGroup" || true + + break + else + echo "❌ FAILED: WebLogic deployment failed with image: $image, trying next..." + # Clean up failed deployment + echo "Cleaning up failed resource group: $resourceGroup" + az group delete --yes --no-wait --verbose --name "$resourceGroup" || true + fi + echo "::endgroup::" + done + + if [ "$success" = "false" ]; then + echo "💥 All images failed!" exit 1 + else + echo "🎉 Workflow succeeded with image: ${{ env.successful_image }}" fi - - name: Configure network security group - id: configure-nsg - run: | - nsg=$(az network nsg list \ - --resource-group $resourceGroup \ - --query "[0].name" -o tsv) - - echo "Allow access to ${adminConsolePort}" - az network nsg rule update \ - --resource-group $resourceGroup \ - --nsg-name ${nsg} \ - --name WebLogicAdminChannelPort \ - --access Allow \ - --source-address-prefixes 10.0.0.0/24 - - name: Query public IP of AdminServer VM - id: query-wls-admin-ip - run: | - echo "query public ip" - publicIP=$(az vm show \ - --resource-group $resourceGroup \ - --name $adminVMName -d \ - --query publicIps -o tsv) - echo "wlsPublicIP=${publicIP}" >> $GITHUB_ENV - - - name: Verify WebLogic Server Access - id: verify-wls-access - run: | - echo "Verifying Weblogic Server Access" - echo ${wlsPublicIP} - bash ${{ env.adminOfferPath }}/test/scripts/verify-wls-access.sh <<< "${wlsPublicIP} ${adminConsolePort}" - - - name: Delete Resource Group - id: delete-resource-group - if: always() - run: | - echo "delete... " $resourceGroup - az group delete --yes --no-wait --verbose --name $resourceGroup cleanup-github-resource: needs: deploy-weblogic-admin @@ -376,6 +451,11 @@ jobs: run: | echo "delete... " $resourceGroup az group delete --yes --no-wait --verbose --name ${{ env.resourceGroupForDependency }} + - name: Delete Resource Group + id: delete-resource-group + run: | + echo "delete resource group with prefix:" ${{ env.resourceGroupPrefix }} + az group list --query "[?starts_with(name, '${{ env.resourceGroupPrefix }}')].[name]" -o tsv | xargs -I {} az group delete --name {} --yes --no-wait summary: needs: deploy-weblogic-admin diff --git a/.github/workflows/testWlsVmCluster.yml b/.github/workflows/testWlsVmCluster.yml index d1a5db176..451417b08 100644 --- a/.github/workflows/testWlsVmCluster.yml +++ b/.github/workflows/testWlsVmCluster.yml @@ -3,21 +3,33 @@ # https://oss.oracle.com/licenses/upl/ name: Test Configured Cluster on VM +run-name: Test Configured Cluster on VM with `db`:${{ inputs.databaseType }} + on: workflow_dispatch: inputs: - ref: - description: 'Specify Git Ref if needed.' - required: false - default: 'refs/heads/main' location: description: 'The location for the resources' required: true - default: eastus + default: centralus + databaseType: + description: 'Database connection' + required: true + default: 'mssqlserver' + type: choice + options: + - mssqlserver + - mssqlserver-passwordless + - postgresql(flexible) + - postgresql-passwordless(flexible) + configurations_for_it: + description: "JSON string of environment variables used for IT" + required: false + default: '{}' # Allows you to run this workflow using GitHub APIs # PERSONAL_ACCESS_TOKEN= # REPO_NAME=oracle/weblogic-azure/weblogic-azure-vm/arm-oraclelinux-wls-cluster - # curl --verbose -XPOST -u "mriccell:${PERSONAL_ACCESS_TOKEN}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/${REPO_NAME}/dispatches --data '{"event_type": "test-vm-cluster", "client_payload": {"ref": "refs/heads/main"}}' + # curl --verbose -XPOST -u "mriccell:${PERSONAL_ACCESS_TOKEN}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/${REPO_NAME}/dispatches --data '{"event_type": "test-vm-cluster", "client_payload": {}}' repository_dispatch: types: [test-vm-cluster,integration-test-all] @@ -26,7 +38,8 @@ env: adminPassword: ${{ secrets.WLS_PSW }} dbAdminUser: weblogic dbName: wlsdb${{ github.run_id }}${{ github.run_number }} - dbServerName: weblogicdb + dbServerName: weblogicdb-${{ github.run_id }}-${{ github.run_number }} + uamiName: uami${{ github.run_id }}${{ github.run_number }} gitEmail: ${{ secrets.USER_EMAIL }} gitToken: ${{ secrets.GIT_TOKEN }} gitUserName: ${{ secrets.USER_NAME }} @@ -35,13 +48,27 @@ env: offerName: arm-oraclelinux-wls-cluster offerPath: weblogic-azure/weblogic-azure-vm/arm-oraclelinux-wls-cluster repoName: weblogic-azure - repoOwner: ${{ secrets.USER_NAME }} - resourceGroupForDependency: wlsd-${{ github.run_id }}-${{ github.run_number }} - resourceGroupPrefix: ${{ github.run_id }}-${{ github.run_number }} + repoOwner: ${{ github.repository_owner }} + resourceGroupForDependency: wlsd-${{ github.repository_owner }}-${{ github.run_id }}-${{ github.run_number }} + resourceGroupPrefix: wls-${{ github.repository_owner }}-${{ github.run_id }}-${{ github.run_number }} testbranchName: cicd-${{ github.run_id }}-${{ github.run_number }} wlsDomainName: wlsd wlsPassword: ${{ secrets.WLS_PSW }} wlsUserName: weblogic + ref: ${{ github.ref_name }} + images: | + owls-141100-jdk11-ol91;Oracle:weblogic-141100-jdk11-ol91:owls-141100-jdk11-ol91;latest + owls-141100-jdk11-ol87;Oracle:weblogic-141100-jdk11-ol87:owls-141100-jdk11-ol87;latest + owls-141100-jdk8-ol91;Oracle:weblogic-141100-jdk8-ol91:owls-141100-jdk8-ol91;latest + owls-141100-jdk8-ol87;Oracle:weblogic-141100-jdk8-ol87:owls-141100-jdk8-ol87;latest + owls-122140-jdk8-ol91;Oracle:weblogic-122140-jdk8-ol91:owls-122140-jdk8-ol91;latest + owls-122140-jdk8-ol87;Oracle:weblogic-122140-jdk8-ol87:owls-122140-jdk8-ol87;latest + owls-122140-jdk8-ol76;Oracle:weblogic-122140-jdk8-ol76:owls-122140-jdk8-ol7;latest + owls-141100-jdk8-ol76;Oracle:weblogic-141100-jdk8-ol76:owls-141100-jdk8-ol7;latest + owls-141100-jdk11-ol76;Oracle:weblogic-141100-jdk11-ol76:owls-141100-jdk11-ol7;latest + owls-122140-jdk8-rhel76;Oracle:weblogic-122140-jdk8-rhel76:owls-122140-jdk8-rhel76;latest + owls-141100-jdk8-rhel76;Oracle:weblogic-141100-jdk8-rhel76:owls-141100-jdk8-rhel76;latest + owls-141100-jdk11-rhel76;Oracle:weblogic-141100-jdk11-rhel76:owls-141100-jdk11-rhel76;latest jobs: preflight: @@ -53,22 +80,17 @@ jobs: - name: Setup environment variables id: setup-env-variables-based-on-dispatch-event run: | - location=eastus # default value + location=centralus # default value if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then - ref=${{ github.event.inputs.ref }} location=${{ github.event.inputs.location }} - else - ref=${{ github.event.client_payload.ref }} + else location=${{ github.event.client_payload.location }} fi - if [ -z "$ref" ]; then - ref='refs/heads/main' - fi - echo "##[set-output name=ref;]${ref}" + echo "##[set-output name=location;]${location}" - echo "ref=${ref}" >> $GITHUB_ENV echo "location=${location}" >> $GITHUB_ENV + - uses: actions/checkout@v2.3.4 - name: Set up Maven with GitHub token uses: ./.github/actions/setupmaven @@ -90,7 +112,7 @@ jobs: with: repository: ${{env.repoOwner}}/${{env.repoName}} path: ${{env.repoName}} - ref: ${{ env.ref }} + - name: Build and test ${{ env.offerName }} run: | mvn -Ptemplate-validation-tests clean install --file ${offerPath}/pom.xml -Dgit.repo.owner=${{ env.repoOwner }} -Dgit.tag=${{ env.ref }} @@ -158,206 +180,32 @@ jobs: run: | echo "create resource group" ${{ env.resourceGroupForDependency }} az group create --verbose --name ${{ env.resourceGroupForDependency }} --location ${location} - - uses: actions/checkout@v2.3.4 - - name: Set up PostgreSQL Flexible Server that allows access from Azure services - uses: ./.github/actions/createPostgresqlFlexibleServer - with: - dbAdminUser: ${{ env.dbAdminUser }} - dbName: ${{ env.dbName }} - dbPassword: ${{ env.wlsPassword }} - dbServerName: ${{ env.dbServerName }} - location: ${{ env.location }} - resourceGroupName: ${{ env.resourceGroupForDependency }} deploy-weblogic-cluster: needs: [deploy-dependencies, preflight] runs-on: ubuntu-latest - strategy: - max-parallel: 1 - fail-fast: false - matrix: - images: - [ - "owls-141100-jdk11-ol91;Oracle:weblogic-141100-jdk11-ol91:owls-141100-jdk11-ol91;latest", - "owls-141100-jdk11-ol87;Oracle:weblogic-141100-jdk11-ol87:owls-141100-jdk11-ol87;latest", - "owls-141100-jdk8-ol91;Oracle:weblogic-141100-jdk8-ol91:owls-141100-jdk8-ol91;latest", - "owls-141100-jdk8-ol87;Oracle:weblogic-141100-jdk8-ol87:owls-141100-jdk8-ol87;latest", - "owls-122140-jdk8-ol91;Oracle:weblogic-122140-jdk8-ol91:owls-122140-jdk8-ol91;latest", - "owls-122140-jdk8-ol87;Oracle:weblogic-122140-jdk8-ol87:owls-122140-jdk8-ol87;latest", - "owls-122140-jdk8-ol76;Oracle:weblogic-122140-jdk8-ol76:owls-122140-jdk8-ol7;latest", - "owls-141100-jdk8-ol76;Oracle:weblogic-141100-jdk8-ol76:owls-141100-jdk8-ol7;latest", - "owls-141100-jdk11-ol76;Oracle:weblogic-141100-jdk11-ol76:owls-141100-jdk11-ol7;latest", - "owls-122140-jdk8-rhel76;Oracle:weblogic-122140-jdk8-rhel76:owls-122140-jdk8-rhel76;latest", - "owls-141100-jdk8-rhel76;Oracle:weblogic-141100-jdk8-rhel76:owls-141100-jdk8-rhel76;latest", - "owls-141100-jdk11-rhel76;Oracle:weblogic-141100-jdk11-rhel76:owls-141100-jdk11-rhel76;latest" - ] + env: ${{ fromJson(inputs.configurations_for_it) }} steps: - name: Initialize environment variables run: | echo "location=${{needs.preflight.outputs.location}}" >> $GITHUB_ENV - - name: Checkout ${{env.repoOwner}}/${{env.repoName}} - uses: actions/checkout@v2 + + - name: Checkout weblogic-azure repository + uses: actions/checkout@v4 with: - repository: ${{env.repoOwner}}/${{env.repoName}} path: ${{env.repoName}} + - name: Download artifact for deployment uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: - path: ${{ needs.preflight.outputs.artifactName }} name: ${{ needs.preflight.outputs.artifactName }} + path: ${{needs.preflight.outputs.artifactName}} + - uses: azure/login@v1 id: azure-login with: creds: ${{ secrets.AZURE_CREDENTIALS }} - - name: Get Image SKU - id: image-sku - run: | - imageUrn="${{ matrix.images }}" - sku=${imageUrn%%;*} - echo "sku=${sku}" >> $GITHUB_ENV - echo ${resourceGroupPrefix} - resourceGroup=$(echo "${resourceGroupPrefix}-${sku}" | sed "s/_//g") - echo "resourceGroup=${resourceGroup}" >> $GITHUB_ENV - - name: Create Resource Group - id: create-resource-group - run: | - echo "create resource group" $resourceGroup - az group create --verbose --name $resourceGroup --location ${location} - - - name: Prepare deployed parameters and test script - id: prepare-deployed-parameters-and-test-script - run: | - repoPath=${GITHUB_REPOSITORY//\//\\/} - bash ${{ env.offerPath }}/test/scripts/gen-parameters-deploy.sh <<< "${{ env.offerPath }}/test/scripts/parameters-test.json \ - $repoPath \ - ${{ env.testbranchName }} \ - ${{ env.location }} \ - ${{ env.wlsPassword }} \ - ${{ env.wlsUserName }} \ - ${{ env.wlsDomainName }} \ - ${{ matrix.images }} \ - ${{ env.dbServerName }} \ - ${{ env.dbName }} \ - ${{ env.wlsPassword }} \ - ${{ env.dbAdminUser }} \ - ${{ env.wlsPassword }}" - - - name: Accept Image Terms - id: accept-terms - run: | - echo "accept terms for " "${{ matrix.images }}" - rawUrn="${{ matrix.images }}" - publisherAndName=$(echo ${rawUrn} | grep -o ";.*:" | sed "s/;//g") - imageVersion=${rawUrn##*;} - az vm image terms accept --urn ${publisherAndName}${sku}:${imageVersion} - - name: Deploy WebLogic Server Cluster Domain offer - id: deploy-wls-cluster - run: | - artifactName=${{ needs.preflight.outputs.artifactName }} - echo "artifactName=${{ needs.preflight.outputs.artifactName }}" >> $GITHUB_ENV - - az deployment group create \ - --verbose \ - --resource-group $resourceGroup \ - --name wls-cluster-node \ - --parameters ${{ env.offerPath }}/test/scripts/parameters-test.json \ - --template-file ${artifactName}/mainTemplate.json - - export adminVMName=$(az deployment group show \ - --resource-group $resourceGroup \ - --name wls-cluster-node \ - --query "properties.outputs.adminVMName.value" -o tsv) - echo "adminVMName=${adminVMName}" >> $GITHUB_ENV - - - name: Configure network security group - id: configure-nsg - run: | - nsg=$(az network nsg list \ - --resource-group $resourceGroup \ - --query "[0].name" -o tsv) - echo "Allow access to ${adminConsolePort}" - az network nsg rule update \ - --resource-group $resourceGroup \ - --nsg-name ${nsg} \ - --name WebLogicAdminChannelPort \ - --access Allow \ - --source-address-prefixes 10.0.0.0/24 - - - name: Verify system services at admin server - id: verify-admin-service - run: | - echo "Verifying WebLogic services at admin server" - message=$(az vm run-command invoke \ - --resource-group $resourceGroup \ - --name $adminVMName \ - --command-id RunShellScript \ - --scripts @${{ env.offerPath }}/test/scripts/verify-admin-services.sh \ - --query value[*].message) - - if [[ $message == *"not in active (running) state"* ]]; then - echo "Error: $message" - exit 1 - fi - - - name: Verify wls managed server services - id: verify-msservice - run: | - managedServerVMNamePrefix=$(az deployment group show \ - --resource-group $resourceGroup \ - --name wls-cluster-node \ - --query "properties.outputs.managedServerVMNamePrefix.value" -o tsv) - echo "managedServerVMNamePrefix=${managedServerVMNamePrefix}" >> $GITHUB_ENV - - managedServer1="${managedServerVMNamePrefix}1" - - echo "Verifying WebLogic services at admin server" - message=$(az vm run-command invoke \ - --resource-group $resourceGroup \ - --name $managedServer1 \ - --command-id RunShellScript \ - --scripts @${{ env.offerPath }}/test/scripts/verify-node-services.sh \ - --query value[*].message) - - if [[ $message == *"not in active (running) state"* ]]; then - echo "Error: $message" - exit 1 - fi - - - name: Query public IP of AdminServer VM - id: query-wls-admin-ip - run: | - echo "query public ip" - publicIP=$(az vm show \ - --resource-group $resourceGroup \ - --name $adminVMName -d \ - --query publicIps -o tsv) - # echo environment variable - echo "wlsPublicIP=${publicIP}" >> $GITHUB_ENV - - - name: Verify WebLogic Server Access - id: verify-wls-access - run: | - echo "Verifying Weblogic Server Access" - bash ${{ env.offerPath }}/test/scripts/verify-wls-access.sh <<< "$wlsPublicIP ${adminConsolePort} $wlsUserName $wlsPassword $managedServers" - - - name: Verify WebLogic Managed Server LifeCycle check - id: verify-server-lifecycle - run: | - echo "Verifying Weblogic managed server lifecycle" - bash ${{ env.offerPath }}/test/scripts/verify-servers-lifecycle.sh <<< "$wlsUserName ${wlsPassword} $wlsPublicIP $adminConsolePort $managedServers" - - - name: Query appGatewayURL of appgateway deployment - id: query-agwurl - run: | - echo "query appgatewayURL" - export appGatewayURL=$(az deployment group show \ - --resource-group $resourceGroup \ - --name wls-cluster-node \ - --query "properties.outputs.appGatewayURL.value" -o tsv) - - echo "appGatewayURL=${appGatewayURL}" >> $GITHUB_ENV - - name: Checkout WebLogic-Cafe id: checkout-webapp uses: actions/checkout@v2 @@ -371,41 +219,264 @@ jobs: echo "build the WebLogic Cafe web app" mvn -DskipTests clean install --file weblogic-on-azure/javaee/weblogic-cafe/pom.xml - - name: Query adminVMsver DNS - id: query-adminvmdns - run: | - echo "query public ip id of $adminVMName" - adminNicId=$(az vm show \ - --resource-group $resourceGroup \ - --name $adminVMName \ - --query networkProfile.networkInterfaces[0].id -o tsv) - adminPublicIPId=$(az network nic show --id ${adminNicId} --query ipConfigurations[0].publicIPAddress.id -o tsv) - echo "query adminVMsver DNS for $adminVMName" - adminVMDNS=$(az network public-ip show \ - --id "${adminPublicIPId}" \ - --query dnsSettings.fqdn -o tsv) - echo "save the adminVMDNS in environment variable" - echo "adminVMDNS=${adminVMDNS}" >> $GITHUB_ENV + - name: Provision database + id: database-provision + uses: ./weblogic-azure/.github/actions/database-provision + with: + databaseType: ${{ inputs.databaseType }} + resourceGroup: ${{ env.resourceGroupForDependency }} + uamiName: ${{ env.uamiName }} + location: ${{ env.location }} + dbInstanceName: ${{ env.dbServerName }} + dbPassword: ${{ env.wlsPassword }} + databaseName: ${{ env.dbName }} + dbAdminUser: ${{ env.dbAdminUser }} - - name: Deploy WebLogicCafe app using WebLogic Management Services - id: deploy-webapp - run: | - echo "Deploy WebLogic Cafe to server" - timeout 6m sh -c 'until nc -zv $0 $1; do echo "nc rc: $?"; sleep 5; done' ${adminVMDNS} ${adminConsolePort} - bash ${{ env.offerPath }}/test/scripts/deploy-webapp.sh <<< "$wlsUserName $wlsPassword ${adminVMDNS} ${adminConsolePort} " + - name: Get database parameters + id: database-parameters + uses: ./weblogic-azure/.github/actions/database-parameters + with: + databaseType: ${{ inputs.databaseType }} + uamiId: ${{ steps.database-provision.outputs.uamiId }} + serverHost: ${{ steps.database-provision.outputs.serverHost }} + dbInstanceName: ${{ env.dbServerName }} + databaseName: ${{ env.dbName }} + dbAdminUser: ${{ env.dbAdminUser }} - - name: Verify WebLogicCafe app is successfully deployed - id: verify-webapp-deployment + - name: Provision Azure Vnet + id: vnet-provision + if: ${{ env.virtualNetworkNewOrExisting == 'existing' }} run: | - echo "Verify WebLogicCafe app is successfully deployed" - bash ${{ env.offerPath }}/test/scripts/verify-webapp-deployment.sh <<< "${appGatewayURL}" + echo "Provisioning Azure Vnet with subnet" + az network vnet create \ + --resource-group ${{ env.resourceGroupForDependency }} \ + --name ${{ env.virtualNetworkName }} \ + --address-prefix 10.0.0.0/23 \ + --subnet-name ${{ env.subnetForCluster }} \ + --subnet-prefix 10.0.0.0/26 - - name: Delete Resource Group - id: delete-resource-group - if: always() + echo "Provisioning Azure Subnet for App Gateway" + az network vnet subnet create \ + --resource-group ${{ env.resourceGroupForDependency }} \ + --name ${{ env.subnetForAppGateway }} \ + --vnet-name ${{ env.virtualNetworkName }} \ + --address-prefix 10.0.1.0/24 + + - name: Try each image until one succeeds run: | - echo "delete... " $resourceGroup - az group delete --yes --no-wait --verbose --name $resourceGroup + # Convert multiline string to array + IFS=$'\n' read -d '' -r -a image_array <<< "${{ env.images }}" || true + + success=false + + for image in "${image_array[@]}"; do + if [ -z "$image" ]; then + continue + fi + + echo "::group::Trying image: $image" + + # Set deployment variables for this image + imageUrn="$image" + sku=${imageUrn%%;*} + resourceGroup=$(echo "${resourceGroupPrefix}-${sku}" | sed "s/_//g") + + echo "Deploying with SKU: $sku" + echo "Resource Group: $resourceGroup" + + # Export db variables for envsubst + export databaseType='${{ steps.database-parameters.outputs.databaseType }}' + export enableDB=${{ steps.database-parameters.outputs.enableDB }} + export enablePswlessConnection=${{ steps.database-parameters.outputs.enablePswlessConnection }} + export dsConnectionURL='${{ steps.database-parameters.outputs.dsConnectionURL }}' + export dbUser='${{ steps.database-parameters.outputs.dbUser }}' + export dbIdentity='${{ steps.database-parameters.outputs.dbIdentity }}' + export dbPassword='${{ env.wlsPassword}}' + export dbName='${{ env.dbName }}' + + # Try deployment with this image + if bash -c " + set -e + + # Create Resource Group + echo 'Creating resource group: $resourceGroup' + az group create --verbose --name '$resourceGroup' --location '${location}' + + ## Prepare parameters for Vnet + if [ "${{ env.virtualNetworkNewOrExisting }}" == "existing" ]; then + export virtualNetworkNewOrExisting=${{ env.virtualNetworkNewOrExisting }} + export virtualNetworkResourceGroupName=${{ env.resourceGroupForDependency }} + export virtualNetworkName=${{ env.virtualNetworkName }} + export subnetForCluster=${{ env.subnetForCluster }} + export subnetForAppGateway=${{ env.subnetForAppGateway }} + else + export virtualNetworkNewOrExisting='new' + export virtualNetworkResourceGroupName='$resourceGroup' + export virtualNetworkName='wlscluster-vnet-cluster' + export subnetForCluster='jboss-subnet-for-cluster' + export subnetForAppGateway='appgateway-subnet' + fi + + export repoPath='${GITHUB_REPOSITORY}' + export testbranchName='${{ env.testbranchName }}' + export location='${{ env.location }}' + export adminPasswordOrKey='${{ env.wlsPassword }}' + export wlsusername='${{ env.wlsUserName }}' + export wlsdomainname='${{ env.wlsDomainName }}' + export skuUrnVersion='$image' + export wlspassword='${{ env.wlsPassword }}' + + echo 'Generating parameter file...' + envsubst < './${{ env.offerPath }}/test/scripts/parameters-deploy-template.json' > './${{ env.offerPath }}/test/parameters-deploy-${{ github.job }}.json' + + # Accept Image Terms + echo 'Accepting terms for image: $image' + rawUrn='$image' + publisherAndName=\$(echo \${rawUrn} | grep -o ';.*:' | sed 's/;//g') + imageVersion=\${rawUrn##*;} + az vm image terms accept --urn \${publisherAndName}$sku:\${imageVersion} + + # Deploy WebLogic Server Cluster Domain offer + echo 'Deploying WebLogic Server Cluster...' + az deployment group create \ + --verbose \ + --resource-group '$resourceGroup' \ + --name wls-cluster-node \ + --parameters @'./${{ env.offerPath }}/test/parameters-deploy-${{ github.job }}.json' \ + --template-file '${{needs.preflight.outputs.artifactName}}/mainTemplate.json' + + if [ "${{ env.virtualNetworkNewOrExisting }}" == "existing" ]; then + # If using existing VNet, there are some gaps to verify the deployment using following steps. + echo 'skip following steps, only verify the deployment for existing vnet' + exit 0 + fi + + # Get admin VM name + echo 'Retrieving admin VM name...' + adminVMName=\$(az deployment group show \ + --resource-group '$resourceGroup' \ + --name wls-cluster-node \ + --query 'properties.outputs.adminVMName.value' -o tsv) + + # Configure network security group + echo 'Configuring network security group...' + nsg=\$(az network nsg list \ + --resource-group '$resourceGroup' \ + --query '[0].name' -o tsv) + + az network nsg rule update \ + --resource-group '$resourceGroup' \ + --nsg-name \${nsg} \ + --name WebLogicAdminChannelPort \ + --access Allow \ + --source-address-prefixes 10.0.0.0/24 + + # Verify system services at admin server + echo 'Verifying WebLogic services at admin server...' + message=\$(az vm run-command invoke \ + --resource-group '$resourceGroup' \ + --name \$adminVMName \ + --command-id RunShellScript \ + --scripts @'${{ env.offerPath }}/test/scripts/verify-admin-services.sh' \ + --query value[*].message) + + if [[ \$message == *'not in active (running) state'* ]]; then + echo 'Error: \$message' + exit 1 + fi + + # Verify wls managed server services + echo 'Verifying WebLogic managed server services...' + managedServerVMNamePrefix=\$(az deployment group show \ + --resource-group '$resourceGroup' \ + --name wls-cluster-node \ + --query 'properties.outputs.managedServerVMNamePrefix.value' -o tsv) + + managedServer1=\"\${managedServerVMNamePrefix}1\" + + message=\$(az vm run-command invoke \ + --resource-group '$resourceGroup' \ + --name \$managedServer1 \ + --command-id RunShellScript \ + --scripts @'${{ env.offerPath }}/test/scripts/verify-node-services.sh' \ + --query value[*].message) + + if [[ \$message == *'not in active (running) state'* ]]; then + echo 'Error: \$message' + exit 1 + fi + + # Get public IP + publicIP=\$(az vm show \ + --resource-group '$resourceGroup' \ + --name \$adminVMName -d \ + --query publicIps -o tsv) + + # Verify WebLogic Server Access + echo 'Verifying WebLogic Server Access...' + bash '${{ env.offerPath }}/test/scripts/verify-wls-access.sh' <<< \"\${publicIP} ${adminConsolePort} $wlsUserName $wlsPassword $managedServers\" + + # Verify WebLogic Managed Server LifeCycle check + echo 'Verifying WebLogic managed server lifecycle...' + bash '${{ env.offerPath }}/test/scripts/verify-servers-lifecycle.sh' <<< \"$wlsUserName ${wlsPassword} \${publicIP} $adminConsolePort $managedServers\" + + # Query appGatewayURL + echo 'Querying app gateway URL...' + appGatewayURL=\$(az deployment group show \ + --resource-group '$resourceGroup' \ + --name wls-cluster-node \ + --query 'properties.outputs.appGatewayURL.value' -o tsv) + + # Checkout WebLogic-Cafe (done outside the loop) + + # Query admin VM DNS + echo 'Querying admin VM DNS...' + adminNicId=\$(az vm show \ + --resource-group '$resourceGroup' \ + --name \$adminVMName \ + --query networkProfile.networkInterfaces[0].id -o tsv) + adminPublicIPId=\$(az network nic show --id \${adminNicId} --query ipConfigurations[0].publicIPAddress.id -o tsv) + adminVMDNS=\$(az network public-ip show \ + --id \"\${adminPublicIPId}\" \ + --query dnsSettings.fqdn -o tsv) + + # Deploy WebLogicCafe app (need to checkout and build first) + echo 'Deploying WebLogic Cafe app...' + timeout 6m sh -c 'until nc -zv \$0 \$1; do echo \"nc rc: \$?\"; sleep 5; done' \${adminVMDNS} ${adminConsolePort} + bash '${{ env.offerPath }}/test/scripts/deploy-webapp.sh' <<< \"$wlsUserName $wlsPassword \${adminVMDNS} ${adminConsolePort}\" + + # Verify WebLogicCafe app deployment + echo 'Verifying WebLogic Cafe app deployment...' + bash '${{ env.offerPath }}/test/scripts/verify-webapp-deployment.sh' <<< \"\${appGatewayURL}\" + + echo 'SUCCESS: All verification steps passed!' + exit 0 + "; then + echo "✅ SUCCESS: WebLogic cluster deployment succeeded with image: $image" + echo "successful_image=$image" >> $GITHUB_ENV + echo "successful_resource_group=$resourceGroup" >> $GITHUB_ENV + success=true + + # Clean up successful deployment + echo "Cleaning up resource group: $resourceGroup" + az group delete --yes --no-wait --verbose --name "$resourceGroup" || true + + break + else + echo "❌ FAILED: WebLogic cluster deployment failed with image: $image, trying next..." + # Clean up failed deployment + echo "Cleaning up failed resource group: $resourceGroup" + az group delete --yes --no-wait --verbose --name "$resourceGroup" || true + fi + echo "::endgroup::" + done + + if [ "$success" = "false" ]; then + echo "💥 All images failed!" + exit 1 + else + echo "🎉 Workflow succeeded with image: ${{ env.successful_image }}" + fi cleanup-github-resource: needs: deploy-weblogic-cluster @@ -426,16 +497,30 @@ jobs: if: always() needs: deploy-weblogic-cluster runs-on: ubuntu-latest + env: ${{ fromJson(inputs.configurations_for_it) }} steps: - uses: azure/login@v1 id: azure-login with: creds: ${{ secrets.AZURE_CREDENTIALS }} - - name: Delete DB Resource Group - id: delete-db-resource-group + - name: Delete resource group for dependency + id: delete-resource-group-for-dependency run: | echo "delete... " $resourceGroup az group delete --yes --no-wait --verbose --name ${{ env.resourceGroupForDependency }} + - name: Delete existing Vnet + id: delete-vnet + if: ${{ env.virtualNetworkNewOrExisting == 'existing' }} + run: | + echo "wait only other resources have been deleted" + sleep 10m + echo "delete vnet" ${{ env.virtualNetworkName }} "in resource group" ${{ env.resourceGroupForDependency }} + az network vnet delete --name ${{ env.virtualNetworkName }} --resource-group ${{ env.resourceGroupForDependency }} + - name: Delete Resource Group + id: delete-resource-group + run: | + echo "delete resource group with prefix:" ${{ env.resourceGroupPrefix }} + az group list --query "[?starts_with(name, '${{ env.resourceGroupPrefix }}')].[name]" -o tsv | xargs -I {} az group delete --name {} --yes --no-wait summary: needs: deploy-weblogic-cluster @@ -446,21 +531,21 @@ jobs: if: ${{ github.repository_owner == 'wls-eng' }} run: | workflow_jobs=$(curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${GITHUB_REPOSITORY}/actions/runs/${{ github.run_id }}/jobs) - critical_job_num=$(echo $workflow_jobs | jq '.jobs | map(select(.name|test("^deploy-weblogic-cluster."))) | length') + critical_job_num=$(echo $workflow_jobs | jq '.jobs | map(select(.name|test("^deploy-weblogic-cluster$"))) | length') echo "$critical_job_num" - succeed_critical_job_num=$(echo $workflow_jobs | jq '.jobs | map(select(.conclusion=="success") | select(.name|test("^deploy-weblogic-cluster."))) | length') + succeed_critical_job_num=$(echo $workflow_jobs | jq '.jobs | map(select(.conclusion=="success") | select(.name|test("^deploy-weblogic-cluster$"))) | length') echo "$succeed_critical_job_num" failed_job_num="$(($critical_job_num-$succeed_critical_job_num))" echo $failed_job_num - if (($failed_job_num >= 2));then - echo "too many jobs failed, send notification to Teams" + if (($failed_job_num >= 1));then + echo "job failed, send notification to Teams" curl ${{ secrets.MSTEAMS_WEBHOOK }} \ -H 'Content-Type: application/json' \ --data-binary @- << EOF { "@context":"http://schema.org/extensions", "@type":"MessageCard", - "text":"$failed_job_num jobs failed in Configured Cluster Offer's workflow, please take a look at: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${{ github.run_id }}" + "text":"$failed_job_num job failed in Configured Cluster Offer's workflow, please take a look at: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${{ github.run_id }}" } EOF fi diff --git a/.github/workflows/testWlsVmDynamicCluster.yml b/.github/workflows/testWlsVmDynamicCluster.yml index 366398c94..6bb532d93 100644 --- a/.github/workflows/testWlsVmDynamicCluster.yml +++ b/.github/workflows/testWlsVmDynamicCluster.yml @@ -3,13 +3,25 @@ # https://oss.oracle.com/licenses/upl/ name: Test Dynamic Cluster on VM +run-name: Test Dynamic Cluster on VM with `db`:${{ inputs.databaseType }} + on: workflow_dispatch: inputs: location: description: 'Location of the resources' required: true - default: 'eastus' + default: 'centralus' + databaseType: + description: 'Database connection' + required: true + default: 'mssqlserver' + type: choice + options: + - mssqlserver + - mssqlserver-passwordless + - postgresql(flexible) + - postgresql-passwordless(flexible) # Allows you to run this workflow using GitHub APIs # PERSONAL_ACCESS_TOKEN= # REPO_NAME=oracle/weblogic-azure/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster @@ -22,12 +34,13 @@ env: adminPassword: ${{ secrets.WLS_PSW }} dbAdminUser: weblogic dbName: wlsdb${{ github.run_id }}${{ github.run_number }} - dbServerName: weblogicdb + dbServerName: db${{ github.run_id }}${{ github.run_number }} + uamiName: uami${{ github.run_id }}${{ github.run_number }} dynamicClusterSize: 1 gitEmail: ${{ secrets.USER_EMAIL }} gitToken: ${{ secrets.GIT_TOKEN }} gitUserName: ${{ secrets.USER_NAME }} - location: eastus + location: centralus nsg: wls-nsg managedServerPrefix: managedServer managedServers: "managedServer1" @@ -36,13 +49,26 @@ env: offerName: arm-oraclelinux-wls-dynamic-cluster offerPath: weblogic-azure/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster repoName: weblogic-azure - repoOwner: ${{ secrets.USER_NAME }} - resourceGroupForDependency: wlsd-${{ github.run_id }}-${{ github.run_number }} - resourceGroupPrefix: wls-${{ github.run_id }}-${{ github.run_number }} + repoOwner: ${{ github.repository_owner }} + resourceGroupForDependency: wlsd-${{ github.repository_owner }}-${{ github.run_id }}-${{ github.run_number }} + resourceGroupPrefix: wls-${{ github.repository_owner }}-${{ github.run_id }}-${{ github.run_number }} testbranchName: cicd-${{ github.run_id }}-${{ github.run_number }} wlsDomainName: dyClusterDomain wlsPassword: ${{ secrets.WLS_PSW }} wlsUserName: weblogic + images: | + owls-141100-jdk11-ol91;Oracle:weblogic-141100-jdk11-ol91:owls-141100-jdk11-ol91;latest + owls-141100-jdk11-ol87;Oracle:weblogic-141100-jdk11-ol87:owls-141100-jdk11-ol87;latest + owls-141100-jdk8-ol91;Oracle:weblogic-141100-jdk8-ol91:owls-141100-jdk8-ol91;latest + owls-141100-jdk8-ol87;Oracle:weblogic-141100-jdk8-ol87:owls-141100-jdk8-ol87;latest + owls-122140-jdk8-ol91;Oracle:weblogic-122140-jdk8-ol91:owls-122140-jdk8-ol91;latest + owls-122140-jdk8-ol87;Oracle:weblogic-122140-jdk8-ol87:owls-122140-jdk8-ol87;latest + owls-122140-jdk8-ol76;Oracle:weblogic-122140-jdk8-ol76:owls-122140-jdk8-ol7;latest + owls-141100-jdk8-ol76;Oracle:weblogic-141100-jdk8-ol76:owls-141100-jdk8-ol7;latest + owls-141100-jdk11-ol76;Oracle:weblogic-141100-jdk11-ol76:owls-141100-jdk11-ol7;latest + owls-122140-jdk8-rhel76;Oracle:weblogic-122140-jdk8-rhel76:owls-122140-jdk8-rhel76;latest + owls-141100-jdk8-rhel76;Oracle:weblogic-141100-jdk8-rhel76:owls-141100-jdk8-rhel76;latest + owls-141100-jdk11-rhel76;Oracle:weblogic-141100-jdk11-rhel76:owls-141100-jdk11-rhel76;latest jobs: preflight: @@ -54,7 +80,7 @@ jobs: - name: Setup environment variables id: setup-env-variables-based-on-dispatch-event run: | - location=eastus # default value + location=centralus # default value if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then location=${{ github.event.inputs.location }} @@ -86,7 +112,7 @@ jobs: repository: ${{env.repoOwner}}/${{env.repoName}} path: ${{env.repoName}} - name: Built and test ${{env.offerName}} - run: mvn -Ptemplate-validation-tests clean install --file ${offerPath}/pom.xml + run: mvn -Ptemplate-validation-tests clean install --file ${{ env.offerPath }}/pom.xml - name: Checkout ${{env.repoOwner}}/${{env.repoName}} uses: actions/checkout@v2 @@ -105,7 +131,7 @@ jobs: echo "create branch $testbranchName" git checkout -b $testbranchName rm -r -f $current/${offerDevPath}/src/main/arm/nestedtemplates/* - cp -r -f $current/${offerPath}/${{ env.offerName }}/target/arm/nestedtemplates/* $current/${offerDevPath}/src/main/arm/nestedtemplates/ + cp -r -f $current/${{ env.offerPath }}/${{ env.offerName }}/target/arm/nestedtemplates/* $current/${offerDevPath}/src/main/arm/nestedtemplates/ git status git commit -a -m "hard code pids" git push https://$gitToken@github.com/${GITHUB_REPOSITORY}.git -f @@ -117,19 +143,19 @@ jobs: - name: Validate deployment templates for different combinations of service integration id: validate-deployment-templates run: | - bash ${offerPath}/test/scripts/verify-deployments.sh <<< \ + bash ${{ env.offerPath }}/test/scripts/verify-deployments.sh <<< \ "${{ github.run_id }}${{ github.run_number }} ${location} \ - ${offerPath}/${offerName}/target/arm/mainTemplate.json \ - ${GITHUB_REPOSITORY} ${testbranchName} ${offerPath}/test/scripts" + ${{ env.offerPath }}/${offerName}/target/arm/mainTemplate.json \ + ${GITHUB_REPOSITORY} ${testbranchName} ${{ env.offerPath }}/test/scripts" - name: Generate artifact file name and path id: artifact_file run: | version=$(mvn -q -Dexec.executable=echo -Dexec.args='${version.${{ env.offerName }}}' --file weblogic-azure/pom.xml --non-recursive exec:exec) artifactName=${{ env.offerName }}-$version-arm-assembly - unzip ${offerPath}/${{ env.offerName }}/target/$artifactName.zip -d ${offerPath}/${{ env.offerName }}/target/$artifactName + unzip ${{ env.offerPath }}/${{ env.offerName }}/target/$artifactName.zip -d ${{ env.offerPath }}/${{ env.offerName }}/target/$artifactName echo "##[set-output name=artifactName;]${artifactName}" - echo "##[set-output name=artifactPath;]${offerPath}/${{ env.offerName }}/target/$artifactName" + echo "##[set-output name=artifactPath;]${{ env.offerPath }}/${{ env.offerName }}/target/$artifactName" - name: Archive ${{env.offerName}} template uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: success() @@ -153,257 +179,272 @@ jobs: run: | echo "create resource group" ${{ env.resourceGroupForDependency }} az group create --verbose --name ${{ env.resourceGroupForDependency }} --location ${location} - - uses: actions/checkout@v2.3.4 - - name: Set up PostgreSQL Flexible Server that allows access from Azure services - uses: ./.github/actions/createPostgresqlFlexibleServer - with: - dbAdminUser: ${{ env.dbAdminUser }} - dbName: ${{ env.dbName }} - dbPassword: ${{ env.wlsPassword }} - dbServerName: ${{ env.dbServerName }} - location: ${{ env.location }} - resourceGroupName: ${{ env.resourceGroupForDependency }} deploy-weblogic-cluster: needs: [preflight, deploy-dependencies] runs-on: ubuntu-latest - strategy: - max-parallel: 1 - fail-fast: false - matrix: - images: - [ - "owls-141100-jdk11-ol91;Oracle:weblogic-141100-jdk11-ol91:owls-141100-jdk11-ol91;latest", - "owls-141100-jdk11-ol87;Oracle:weblogic-141100-jdk11-ol87:owls-141100-jdk11-ol87;latest", - "owls-141100-jdk8-ol91;Oracle:weblogic-141100-jdk8-ol91:owls-141100-jdk8-ol91;latest", - "owls-141100-jdk8-ol87;Oracle:weblogic-141100-jdk8-ol87:owls-141100-jdk8-ol87;latest", - "owls-122140-jdk8-ol91;Oracle:weblogic-122140-jdk8-ol91:owls-122140-jdk8-ol91;latest", - "owls-122140-jdk8-ol87;Oracle:weblogic-122140-jdk8-ol87:owls-122140-jdk8-ol87;latest", - "owls-122140-jdk8-ol76;Oracle:weblogic-122140-jdk8-ol76:owls-122140-jdk8-ol7;latest", - "owls-141100-jdk8-ol76;Oracle:weblogic-141100-jdk8-ol76:owls-141100-jdk8-ol7;latest", - "owls-141100-jdk11-ol76;Oracle:weblogic-141100-jdk11-ol76:owls-141100-jdk11-ol7;latest", - "owls-122140-jdk8-rhel76;Oracle:weblogic-122140-jdk8-rhel76:owls-122140-jdk8-rhel76;latest", - "owls-141100-jdk8-rhel76;Oracle:weblogic-141100-jdk8-rhel76:owls-141100-jdk8-rhel76;latest", - "owls-141100-jdk11-rhel76;Oracle:weblogic-141100-jdk11-rhel76:owls-141100-jdk11-rhel76;latest" - ] steps: - name: Initialize environment variables run: | echo "location=${{needs.preflight.outputs.location}}" >> $GITHUB_ENV - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: 'microsoft' - java-version: '11' - - name: Checkout ${{env.repoOwner}}/${{env.repoName}} + + - name: Checkout weblogic-azure repository uses: actions/checkout@v4 with: - repository: ${{env.repoOwner}}/${{env.repoName}} path: ${{env.repoName}} + - name: Download artifact for deployment uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: - path: ${{needs.preflight.outputs.artifactName}} name: ${{ needs.preflight.outputs.artifactName }} + path: ${{needs.preflight.outputs.artifactName}} + - uses: azure/login@v1 id: azure-login with: creds: ${{ secrets.AZURE_CREDENTIALS }} - - name: Get Image SKU - id: image-sku - run: | - imageUrn="${{ matrix.images }}" - sku=${imageUrn%%;*} - echo "sku=${sku}" >> $GITHUB_ENV - echo ${resourceGroupPrefix} - resourceGroup=$(echo "${resourceGroupPrefix}-${sku}" | sed "s/_//g") - echo "resourceGroup=${resourceGroup}" >> $GITHUB_ENV - - name: Create Resource Group - id: create-resource-group - run: | - echo "create resource group" $resourceGroup - az group create --verbose --name $resourceGroup --location ${location} - - - name: Prepare deployed parameters and test script - id: prepare-deployed-parameters-and-test-script - run: | - imageUrn="${{ matrix.images }}" - - echo "Generate selfsigned certificate" - echo $JAVA_HOME - bash ${offerPath}/test/scripts/generate-selfsigned-keystore.sh <<< \ - "${wlsPassword} ${wlsPassword} ${wlsPassword}" - sslIdentityData=$(cat identity.jks | base64 -w 0) - - echo "Generate deployment parameters..." - bash ${offerPath}/test/scripts/gen-parameters-deploy.sh <<< \ - "${offerPath}/test/scripts/parameters-test.json \ - $location \ - $wlsPassword \ - $wlsDomainName \ - $wlsUserName \ - $wlsPassword \ - $managedServerPrefix \ - $maxDynamicClusterSize \ - $dynamicClusterSize \ - $imageUrn \ - $testbranchName \ - $GITHUB_REPOSITORY \ - ${{ env.dbServerName }} \ - ${{ env.dbName }} \ - ${{ env.wlsPassword }} \ - ${{ env.dbAdminUser }} \ - ${sslIdentityData}" - - - name: Accept Image Terms - id: accept-terms - run: | - echo "accept terms for " "${{ matrix.images }}" - rawUrn="${{ matrix.images }}" - publisherAndName=$(echo ${rawUrn} | grep -o ";.*:" | sed "s/;//g") - imageVersion=${rawUrn##*;} - az vm image terms accept --urn ${publisherAndName}${sku}:${imageVersion} - - - name: Deploy WebLogic Server Dynamic Cluster Domain offer - id: deploy-wls-dycluster - run: | - artifactName=${{ needs.preflight.outputs.artifactName }} - echo "artifactName=${{ needs.preflight.outputs.artifactName }}" >> $GITHUB_ENV - - az deployment group create \ - --verbose \ - --resource-group $resourceGroup \ - --name wls-dycluster-node \ - --parameters @${offerPath}/test/scripts/parameters-test.json \ - --template-file ${artifactName}/mainTemplate.json - - export adminVMName=$(az deployment group show \ - --resource-group $resourceGroup \ - --name wls-dycluster-node \ - --query "properties.outputs.adminVMName.value" -o tsv) - echo "adminVMName=${adminVMName}" >> $GITHUB_ENV - - - name: Verify wls admin services - id: veriy-admin-service - run: | - echo "Verifying WebLogic services at admin server" - message=$(az vm run-command invoke \ - --resource-group $resourceGroup \ - --name $adminVMName \ - --command-id RunShellScript \ - --scripts @${{ env.offerPath }}/test/scripts/verify-admin-services.sh \ - --query value[*].message) - - if [[ $message == *"not in active (running) state"* ]]; then - echo "Error: $message" - exit 1 - fi - - - name: Verify wls managed server services - id: veriy-msservice - run: | - managedServerVMNamePrefix=$(az deployment group show \ - --resource-group $resourceGroup \ - --name wls-dycluster-node \ - --query "properties.outputs.managedServerVMNamePrefix.value" -o tsv) - echo "managedServerVMNamePrefix=${managedServerVMNamePrefix}" >> $GITHUB_ENV - - managedServer1="${managedServerVMNamePrefix}1" - - echo "Verifying WebLogic services at admin server" - message=$(az vm run-command invoke \ - --resource-group $resourceGroup \ - --name $managedServer1 \ - --command-id RunShellScript \ - --scripts @${{ env.offerPath }}/test/scripts/verify-node-services.sh \ - --query value[*].message) - - if [[ $message == *"not in active (running) state"* ]]; then - echo "Error: $message" - exit 1 - fi - - name: Query public IP of AdminServer VM - id: query-wls-admin-ip - run: | - echo "query public ip" - publicIP=$(az vm show \ - --resource-group $resourceGroup \ - --name $adminVMName -d \ - --query publicIps -o tsv) - # echo environment variable - echo "wlsPublicIP=${publicIP}" >> $GITHUB_ENV - - - name: Verify WebLogic Server Access - id: verify-wls-access - run: | - echo "Verifying Weblogic Server Access" - bash ${offerPath}/test/scripts/verify-wls-access.sh <<< "$wlsPublicIP ${adminConsolePort} $wlsUserName $wlsPassword $managedServers" - - - name: Verify WebLogic Managed Server LifeCycle check - id: verify-server-lifecycle - run: | - echo "Verifying Weblogic managed server lifecycle" - bash ${offerPath}/test/scripts/verify-servers-lifecycle.sh <<< "$wlsUserName $wlsPassword ${wlsPublicIP} ${adminConsolePort} ${managedServers}" - + - uses: actions/setup-java@v4 + with: + distribution: 'microsoft' + java-version: '11' + - name: Checkout WebLogic-Cafe - id: checkout-webapp uses: actions/checkout@v2 with: repository: azure-javaee/weblogic-on-azure path: weblogic-on-azure - name: Maven build the web app - id: maven-build-webapp run: | echo "build the WebLogic Cafe web app" mvn -DskipTests clean install --file weblogic-on-azure/javaee/weblogic-cafe/pom.xml - - name: Query adminVMsver DNS - id: query-adminvmdns - run: | - echo "query public ip id of $adminVMName" - adminNicId=$(az vm show \ - --resource-group $resourceGroup \ - --name $adminVMName \ - --query networkProfile.networkInterfaces[0].id -o tsv) - adminPublicIPId=$(az network nic show --id ${adminNicId} --query ipConfigurations[0].publicIPAddress.id -o tsv) - echo "query adminVMsver DNS for $adminVMName" - adminVMDNS=$(az network public-ip show \ - --id "${adminPublicIPId}" \ - --query dnsSettings.fqdn -o tsv) - echo "save the adminVMDNS in environment variable" - echo "adminVMDNS=${adminVMDNS}" >> $GITHUB_ENV + - name: Provision database + id: database-provision + uses: ./weblogic-azure/.github/actions/database-provision + with: + databaseType: ${{ inputs.databaseType }} + resourceGroup: ${{ env.resourceGroupForDependency }} + uamiName: ${{ env.uamiName }} + location: ${{ env.location }} + dbInstanceName: ${{ env.dbServerName }} + dbPassword: ${{ env.wlsPassword }} + databaseName: ${{ env.dbName }} + dbAdminUser: ${{ env.dbAdminUser }} - - name: Deploy WebLogicCafe app using WebLogic Management Services - id: deploy-and-verify-webapp - run: | - echo "Deploy WebLogic Cafe to server" - timeout 6m sh -c 'until nc -zv $0 $1; do echo "nc rc: $?"; sleep 5; done' ${adminVMDNS} ${adminConsolePort} - bash ${{ env.offerPath }}/test/scripts/deploy-webapp.sh <<< "$wlsUserName $wlsPassword ${adminVMDNS} ${adminConsolePort} " + - name: Get database parameters + id: database-parameters + uses: ./weblogic-azure/.github/actions/database-parameters + with: + databaseType: ${{ inputs.databaseType }} + uamiId: ${{ steps.database-provision.outputs.uamiId }} + serverHost: ${{ steps.database-provision.outputs.serverHost }} + dbInstanceName: ${{ env.dbServerName }} + databaseName: ${{ env.dbName }} + dbAdminUser: ${{ env.dbAdminUser }} - - name: Query ohsAccessURL from deployment output - id: query-ohsvmdns + - name: Try each image until one succeeds run: | - echo "query ohsAccessURL" - ohsAccessURL=$(az deployment group show \ - --resource-group $resourceGroup \ - --name wls-dycluster-node \ - --query "properties.outputs.ohsAccessURL.value" -o tsv) - echo "ohsAccessURL=${ohsAccessURL}" >> $GITHUB_ENV + # Convert multiline string to array + IFS=$'\n' read -d '' -r -a image_array <<< "${{ env.images }}" || true + + success=false + + for image in "${image_array[@]}"; do + if [ -z "$image" ]; then + continue + fi + + echo "::group::Trying image: $image" + + # Set deployment variables for this image + imageUrn="$image" + sku=${imageUrn%%;*} + resourceGroup=$(echo "${resourceGroupPrefix}-${sku}" | sed "s/_//g") + + echo "Deploying with SKU: $sku" + echo "Resource Group: $resourceGroup" + + # Export db variables for envsubst + export databaseType='${{ steps.database-parameters.outputs.databaseType }}' + export enableDB=${{ steps.database-parameters.outputs.enableDB }} + export enablePswlessConnection=${{ steps.database-parameters.outputs.enablePswlessConnection }} + export dsConnectionURL='${{ steps.database-parameters.outputs.dsConnectionURL }}' + export dbUser='${{ steps.database-parameters.outputs.dbUser }}' + export dbIdentity='${{ steps.database-parameters.outputs.dbIdentity }}' + export dbPassword='${{ env.wlsPassword}}' + export dbName='${{ env.dbName }}' + export dbServerName='${{ env.dbServerName }}' + + # Try deployment with this image + if bash -c " + set -e + + # Create Resource Group + echo 'Creating resource group: $resourceGroup' + az group create --verbose --name '$resourceGroup' --location '${location}' + + # Generate selfsigned certificate + echo 'Generate selfsigned certificate' + bash '${{ env.offerPath }}/test/scripts/generate-selfsigned-keystore.sh' <<< \ + '${wlsPassword} ${wlsPassword} ${wlsPassword}' + + echo 'Current working directory: $(pwd)' + # check whether identity.jks exists + if [ ! -f identity.jks ]; then + echo 'Error: identity.jks not found!' + else + echo 'identity.jks found!' + fi + + # Generate deployment parameters + echo 'Generate deployment parameters...' + export location='${{ env.location }}' + export adminPasswordOrKey='${{ env.wlsPassword }}' + export wlsdomainname='${{ env.wlsDomainName }}' + export wlsusername='${{ env.wlsUserName }}' + export wlspassword='${{ env.wlsPassword }}' + export maxDynamicClusterSize='${{ env.maxDynamicClusterSize }}' + export dynamicClusterSize='${{ env.dynamicClusterSize }}' + export skuUrnVersion='$image' + export testbranchName='${{ env.testbranchName }}' + export managedServerPrefix=${{ env.managedServerPrefix }} + export repoPath='${GITHUB_REPOSITORY}' + export uploadedKeyStoreData=\$(cat identity.jks | base64 -w 0) + + export DOLLAR='$' + echo 'Generating parameter file...' + envsubst < './${{ env.offerPath }}/test/scripts/parameters-deploy-template.json' > './${{ env.offerPath }}/test/parameters-deploy-${{ github.job }}.json' + + # Accept Image Terms + echo 'Accepting terms for image: $image' + rawUrn='$image' + publisherAndName=\$(echo \${rawUrn} | grep -o ';.*:' | sed 's/;//g') + imageVersion=\${rawUrn##*;} + az vm image terms accept --urn \${publisherAndName}$sku:\${imageVersion} + + # Deploy WebLogic Server Dynamic Cluster + echo 'Deploying WebLogic Server Dynamic Cluster...' + echo 'current path is: $(pwd)' + echo 'artifactName is: ${{ needs.preflight.outputs.artifactName }}' + az deployment group create \ + --verbose \ + --resource-group '$resourceGroup' \ + --name wls-dycluster-node \ + --parameters @'${{ env.offerPath }}/test/parameters-deploy-${{ github.job }}.json' \ + --template-file '${{needs.preflight.outputs.artifactName}}/mainTemplate.json' + + # Get admin VM name + adminVMName=\$(az deployment group show \ + --resource-group '$resourceGroup' \ + --name wls-dycluster-node \ + --query 'properties.outputs.adminVMName.value' -o tsv) + + # Verify wls admin services + echo 'Verifying WebLogic admin services...' + message=\$(az vm run-command invoke \ + --resource-group '$resourceGroup' \ + --name \$adminVMName \ + --command-id RunShellScript \ + --scripts @'${{ env.offerPath }}/test/scripts/verify-admin-services.sh' \ + --query value[*].message) + + if [[ \$message == *'not in active (running) state'* ]]; then + echo 'Error: \$message' + exit 1 + fi + + # Verify wls managed server services + echo 'Verifying WebLogic managed server services...' + managedServerVMNamePrefix=\$(az deployment group show \ + --resource-group '$resourceGroup' \ + --name wls-dycluster-node \ + --query 'properties.outputs.managedServerVMNamePrefix.value' -o tsv) + + managedServer1=\"\${managedServerVMNamePrefix}1\" + message=\$(az vm run-command invoke \ + --resource-group '$resourceGroup' \ + --name \$managedServer1 \ + --command-id RunShellScript \ + --scripts @'${{ env.offerPath }}/test/scripts/verify-node-services.sh' \ + --query value[*].message) + + if [[ \$message == *'not in active (running) state'* ]]; then + echo 'Error: \$message' + exit 1 + fi + + # Get public IP + publicIP=\$(az vm show \ + --resource-group '$resourceGroup' \ + --name \$adminVMName -d \ + --query publicIps -o tsv) + + # Verify WebLogic Server Access + echo 'Verifying WebLogic Server Access...' + bash '${{ env.offerPath }}/test/scripts/verify-wls-access.sh' <<< \"\$publicIP ${adminConsolePort} $wlsUserName $wlsPassword $managedServers\" + + # Verify WebLogic Managed Server LifeCycle + echo 'Verifying WebLogic managed server lifecycle...' + bash '${{ env.offerPath }}/test/scripts/verify-servers-lifecycle.sh' <<< \"$wlsUserName $wlsPassword \$publicIP ${adminConsolePort} $managedServers\" + + # Query admin VM DNS + echo 'Querying admin VM DNS...' + adminNicId=\$(az vm show \ + --resource-group '$resourceGroup' \ + --name \$adminVMName \ + --query networkProfile.networkInterfaces[0].id -o tsv) + adminPublicIPId=\$(az network nic show --id \${adminNicId} --query ipConfigurations[0].publicIPAddress.id -o tsv) + adminVMDNS=\$(az network public-ip show \ + --id \"\${adminPublicIPId}\" \ + --query dnsSettings.fqdn -o tsv) + + # Deploy WebLogicCafe app + echo 'Deploying WebLogicCafe app...' + timeout 6m sh -c 'until nc -zv \$0 \$1; do echo \"nc rc: \$?\"; sleep 5; done' \${adminVMDNS} ${adminConsolePort} + bash '${{ env.offerPath }}/test/scripts/deploy-webapp.sh' <<< \"$wlsUserName $wlsPassword \${adminVMDNS} ${adminConsolePort}\" + + # Query OHS Access URL + echo 'Querying OHS Access URL...' + ohsAccessURL=\$(az deployment group show \ + --resource-group '$resourceGroup' \ + --name wls-dycluster-node \ + --query 'properties.outputs.ohsAccessURL.value' -o tsv) + + # Verify WebLogicCafe app deployment + echo 'Verifying WebLogicCafe app deployment...' + bash '${{ env.offerPath }}/test/scripts/verify-webapp-deployment.sh' <<< \"\${ohsAccessURL}\" + + echo 'SUCCESS: All verification steps passed!' + exit 0 + "; then + echo "✅ SUCCESS: WebLogic deployment succeeded with image: $image" + echo "successful_image=$image" >> $GITHUB_ENV + echo "successful_resource_group=$resourceGroup" >> $GITHUB_ENV + success=true + + # Clean up successful deployment + echo "Cleaning up resource group: $resourceGroup" + az group delete --yes --no-wait --verbose --name "$resourceGroup" || true + + break + else + echo "❌ FAILED: WebLogic deployment failed with image: $image, trying next..." + # Clean up failed deployment + echo "Cleaning up failed resource group: $resourceGroup" + # az group delete --yes --no-wait --verbose --name "$resourceGroup" || true + fi + echo "::endgroup::" + done + + if [ "$success" = "false" ]; then + echo "💥 All images failed!" + exit 1 + else + echo "🎉 Workflow succeeded with image: ${{ env.successful_image }}" + fi - - name: Verify WebLogicCafe app is successfully deployed - id: verify-webapp-deployment - run: | - echo "Verify WebLogicCafe app is successfully deployed" - bash ${{ env.offerPath }}/test/scripts/verify-webapp-deployment.sh <<< "${ohsAccessURL}" - - - name: Delete Resource Group - id: delete-resource-group - if: always() - run: | - echo "delete... " $resourceGroup - az group delete --yes --no-wait --verbose --name $resourceGroup cleanup-github-resource: needs: deploy-weblogic-cluster @@ -434,6 +475,11 @@ jobs: run: | echo "delete... " $resourceGroup az group delete --yes --no-wait --verbose --name ${{ env.resourceGroupForDependency }} + - name: Delete Resource Group + id: delete-resource-group + run: | + echo "delete resource group with prefix:" ${{ env.resourceGroupPrefix }} + az group list --query "[?starts_with(name, '${{ env.resourceGroupPrefix }}')].[name]" -o tsv | xargs -I {} az group delete --name {} --yes --no-wait summary: needs: deploy-weblogic-cluster diff --git a/README.md b/README.md index 6a42d10de..f78551fdc 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,13 @@ As part of a broad-ranging partnership between Oracle and Microsoft, this project offers support for running Oracle WebLogic Server in the Azure Virtual Machines and Azure Kubernetes Service (AKS). The partnership includes joint support for a range of Oracle software running on Azure, including Oracle WebLogic, Oracle Linux, and Oracle DB, as well as interoperability between Oracle Cloud Infrastructure (OCI) and Azure. +## Integration tests report +* [![CI Validation for Build](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-build.yaml/badge.svg)](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-build.yaml) +* [![CI Validation for AKS](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-aks.yaml/badge.svg)](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-aks.yaml) +* [![CI Validation for VM Admin](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-vm-admin.yaml/badge.svg)](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-vm-admin.yaml) +* [![CI Validation for VM Cluster](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-vm-cluster.yaml/badge.svg)](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-vm-cluster.yaml) +* [![CI Validation for VM Dynamic Cluster](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-vm-dynamic-cluster.yaml/badge.svg)](https://github.com/oracle/weblogic-azure/actions/workflows/it-validation-vm-dynamic-cluster.yaml) + ## Installation The [Azure Marketplace WebLogic Server Offering](https://azuremarketplace.microsoft.com/en-us/marketplace/apps?search=WebLogic) offers a simplified UI and installation experience over the full power of the Azure Resource Manager (ARM) template. diff --git a/pom.xml b/pom.xml index ea8f54ff2..7da033aea 100644 --- a/pom.xml +++ b/pom.xml @@ -40,12 +40,12 @@ - 1.0.91 + 1.0.92 - 1.0.31 - 1.0.56 - 1.0.730000 - 1.0.54 + 1.0.32 + 1.0.57 + 1.0.740000 + 1.0.55 1.0.7 1.0.3 diff --git a/resources/azure-common.properties b/resources/azure-common.properties index dcbfae78e..45d547e46 100644 --- a/resources/azure-common.properties +++ b/resources/azure-common.properties @@ -1,3 +1,12 @@ +## Use the following command to get the latest 10 API versions for a given resource type +## ```bash +## export NameSpace= +## export ResourceType= +## az provider show --namespace ${NameSpace} --query "resourceTypes[?resourceType=='${ResourceType}'].apiVersions[:10]" \ +## | jq -r '.[][] | select(test("preview$"; "i") | not)' | head -n 10 +## ``` +## + # Microsoft.Authorization/roleAssignments azure.apiVersionForRoleAssignment=2022-04-01 # Microsoft.Authorization/roleDefinitions @@ -7,9 +16,9 @@ azure.apiVersionForContainerRegistries=2023-07-01 # Microsoft.ContainerService/managedClusters azure.apiVersionForManagedClusters=2023-08-01 # Microsoft.Compute/availabilitySets -azure.apiVersionForAvailabilitySets=2023-07-01 +azure.apiVersionForAvailabilitySets=2024-11-01 # Microsoft.Compute/virtualMachines -azure.apiVersionForVirtualMachines=2023-07-01 +azure.apiVersionForVirtualMachines=2024-11-01 # Microsoft.KeyVault/vaults azure.apiVersionForKeyVault=2024-11-01 # Microsoft.KeyVault/vaults/secrets @@ -39,9 +48,9 @@ azure.apiVersionForDeployment=2023-07-01 # Microsoft.Resources/tags azure.apiVersionForTags=2023-07-01 # Microsoft.Storage/storageAccounts -azure.apiVersionForStorage=2023-05-01 +azure.apiVersionForStorage=2025-01-01 # Microsoft.Storage/storageAccounts/fileServices -azure.apiVersionForStorageFileService=2023-05-01 +azure.apiVersionForStorageFileService=2025-01-01 # Microsoft.Monitor/accounts azure.apiVersionForMonitorAccount=2023-04-03 diff --git a/weblogic-azure-aks/src/main/arm/scripts/common.sh b/weblogic-azure-aks/src/main/arm/scripts/common.sh index 5d66cbe8a..43b74eae4 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/common.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/common.sh @@ -50,12 +50,12 @@ export curlMaxTime=120 # seconds export ocrLoginServer="container-registry.oracle.com" export ocrGaImagePath="middleware/weblogic" export ocrCpuImagePath="middleware/weblogic_cpu" -export gitUrl4CpuImages="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/weblogic_cpu_images.json" -export gitUrl4AksWellTestedVersionJsonFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/aks_well_tested_version.json" -export gitUrl4AksToolingWellTestedVersionJsonFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/aks_tooling_well_tested_versions.json" -export gitUrl4WLSToolingFamilyJsonFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/weblogic_tooling_family.json" -export gitUrl4AzureIdentityExtensionsPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/b67a5f95a6c2f590fe8ff938daa298fe7adf7a45/weblogic-azure-aks/src/main/resources/azure-identity-extensions.xml" # PR https://github.com/oracle/weblogic-azure/pull/352 "https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/azure-identity-extensions.xml" -export gitUrl4MySQLDriverPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/mysql-connector-java.xml" +export gitUrl4CpuImages="https://raw.githubusercontent.com/oracle/weblogic-azure/556ebc6bfd92679ceeb843f0a1bdea98a06ca608/weblogic-azure-aks/src/main/resources/weblogic_cpu_images.json" +export gitUrl4AksWellTestedVersionJsonFile="https://raw.githubusercontent.com/oracle/weblogic-azure/556ebc6bfd92679ceeb843f0a1bdea98a06ca608/weblogic-azure-aks/src/main/resources/aks_well_tested_version.json" +export gitUrl4AksToolingWellTestedVersionJsonFile="https://raw.githubusercontent.com/oracle/weblogic-azure/556ebc6bfd92679ceeb843f0a1bdea98a06ca608/weblogic-azure-aks/src/main/resources/aks_tooling_well_tested_versions.json" +export gitUrl4WLSToolingFamilyJsonFile="https://raw.githubusercontent.com/oracle/weblogic-azure/556ebc6bfd92679ceeb843f0a1bdea98a06ca608/weblogic-azure-aks/src/main/resources/weblogic_tooling_family.json" +export gitUrl4AzureIdentityExtensionsPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/556ebc6bfd92679ceeb843f0a1bdea98a06ca608/weblogic-azure-aks/src/main/resources/azure-identity-extensions.xml" +export gitUrl4MySQLDriverPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/556ebc6bfd92679ceeb843f0a1bdea98a06ca608/weblogic-azure-aks/src/main/resources/mysql-connector-java.xml" export optUninstallMaxTry=5 # Max attempts to wait for the operator uninstalled export optUninstallInterval=10 diff --git a/weblogic-azure-aks/src/main/arm/scripts/createVMAndBuildImage.sh b/weblogic-azure-aks/src/main/arm/scripts/createVMAndBuildImage.sh index 1c1c13413..d073f22a7 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/createVMAndBuildImage.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/createVMAndBuildImage.sh @@ -154,7 +154,7 @@ function build_docker_image() { --version 2.0 \ --settings "{ \"fileUris\": [\"${SCRIPT_LOCATION}model.properties\",\"${SCRIPT_LOCATION}genImageModel.sh\",\"${SCRIPT_LOCATION}buildWLSDockerImage.sh\",\"${SCRIPT_LOCATION}common.sh\"]}" \ --protected-settings "{\"commandToExecute\":\"echo ${acrPassword} ${ORACLE_ACCOUNT_PASSWORD} | bash buildWLSDockerImage.sh ${wlsImagePath} ${acrLoginServer} ${acrUser} ${newImageTag} ${WLS_APP_PACKAGE_URLS} ${ORACLE_ACCOUNT_NAME} ${WLS_CLUSTER_SIZE} ${ENABLE_CUSTOM_SSL} ${ENABLE_ADMIN_CUSTOM_T3} ${ENABLE_CLUSTER_CUSTOM_T3} ${USE_ORACLE_IMAGE} ${URL_3RD_DATASOURCE} ${ENABLE_PASSWORDLESS_DB_CONNECTION} ${DB_TYPE} ${CPU_PLATFORM} \"}" - + cleanup_vm } diff --git a/weblogic-azure-aks/src/main/arm/scripts/setupDBConnections.sh b/weblogic-azure-aks/src/main/arm/scripts/setupDBConnections.sh index 9156f292b..3385b0387 100644 --- a/weblogic-azure-aks/src/main/arm/scripts/setupDBConnections.sh +++ b/weblogic-azure-aks/src/main/arm/scripts/setupDBConnections.sh @@ -252,12 +252,14 @@ EOF echo "copy test script ${testDatasourceScript} to pod path /tmp/${dsScriptFileName}" targetDSFilePath=/tmp/${dsScriptFileName} kubectl cp ${testDatasourceScript} -n ${wlsDomainNS} ${podName}:${targetDSFilePath} + echo "execute script to validate data source ${JDBC_DATASOURCE_NAME} in pod ${podName} with wlsContainerName ${wlsContainerName}" kubectl exec ${podName} -n ${wlsDomainNS} -c ${wlsContainerName} -- bash -c "wlst.sh ${targetDSFilePath}" | grep "State is Running" if [ $? == 1 ];then echo_stderr "Failed to configure datasource ${JDBC_DATASOURCE_NAME}. Please make sure the input values are correct." - delete_datasource exit 1 + else + echo "Data source ${JDBC_DATASOURCE_NAME} is configured successfully." fi } diff --git a/weblogic-azure-aks/src/main/bicep/modules/_setupPasswordlessDBConnection.bicep b/weblogic-azure-aks/src/main/bicep/modules/_setupPasswordlessDBConnection.bicep index 64ca5af4e..3b88c7872 100644 --- a/weblogic-azure-aks/src/main/bicep/modules/_setupPasswordlessDBConnection.bicep +++ b/weblogic-azure-aks/src/main/bicep/modules/_setupPasswordlessDBConnection.bicep @@ -62,11 +62,17 @@ var name_jdbcPlugins = { postgresql: 'authenticationPluginClassName=com.azure.identity.extensions.jdbc.postgresql.AzurePostgresqlAuthenticationPlugin' sqlserver: 'authentication=ActiveDirectoryMSI' } -var array_urlJoiner = { +var array_paramJoiner = { mysql: '&' postgresql: '&' sqlserver: ';' } + +var array_urlJoiner = { + mysql: '?' + postgresql: '?' + sqlserver: ';' +} var name_podIdentity = format('{0}-pod-identity-{1}', databaseType, toLower(utcValue)) module pidStart './_pids/_pid.bicep' = { @@ -136,7 +142,7 @@ module configDataSource '_deployment-scripts/_ds-datasource-connection.bicep' = dbConfigurationType: dbConfigurationType dbGlobalTranPro: dbGlobalTranPro dbUser: dbUser - dsConnectionURL: format('{0}{4}{1}{4}{3}={2}', const_connectionString, name_jdbcPlugins[databaseType], reference(items(dbIdentity.userAssignedIdentities)[0].key, const_identityAPIVersion, 'full').properties.clientId, array_msiClientId[databaseType], array_urlJoiner[databaseType]) + dsConnectionURL: format('{0}{4}{1}{5}{2}={3}', const_connectionString, name_jdbcPlugins[databaseType], array_msiClientId[databaseType], reference(items(dbIdentity.userAssignedIdentities)[0].key, const_identityAPIVersion, 'full').properties.clientId, array_urlJoiner[databaseType], array_paramJoiner[databaseType]) enablePswlessConnection: true identity: identity jdbcDataSourceName: jdbcDataSourceName diff --git a/weblogic-azure-aks/src/test/parameters-deploy-template.json b/weblogic-azure-aks/src/test/parameters-deploy-template.json new file mode 100644 index 000000000..5bca0d9c5 --- /dev/null +++ b/weblogic-azure-aks/src/test/parameters-deploy-template.json @@ -0,0 +1,121 @@ +{ + "_artifactsLocation": { + "value": "https://raw.githubusercontent.com/${gitUserName}/weblogic-azure/${testbranchName}/weblogic-azure-aks/src/main/arm/" + }, + "aksAgentPoolNodeCount": { + "value": 3 + }, + "vmSize": { + "value": "${vmSize}" + }, + "appGatewayCertificateOption": { + "value": "generateCert" + }, + "appgwForAdminServer": { + "value": true + }, + "appgwForRemoteConsole": { + "value": true + }, + "appPackageUrls": { + "value": [ + "${appPackageUrls}" + ] + }, + "appReplicas": { + "value": 2 + }, + "createACR": { + "value": true + }, + "createAKSCluster": { + "value": ${createAKSCluster} + }, + "newOrExistingVnetForApplicationGateway": { + "value": "${newOrExistingVnetForApplicationGateway}" + }, + "vnetRGNameForApplicationGateway": { + "value": "${vnetRGNameForApplicationGateway}" + }, + "aksClusterName": { + "value": "${aksClusterName}" + }, + "aksClusterRGName":{ + "value": "${aksClusterRGName}" + }, + "createDNSZone": { + "value": true + }, + "dbGlobalTranPro": { + "value": "EmulateTwoPhaseCommit" + }, + "dbPassword": { + "value": "${dbPassword}" + }, + "dbUser": { + "value": "${dbUser}" + }, + "databaseType": { + "value": "${databaseType}" + }, + "dsConnectionURL": { + "value": "${dsConnectionURL}" + }, + "enablePswlessConnection": { + "value": ${enablePswlessConnection} + }, + "enableAppGWIngress": { + "value": ${enableAppGWIngress} + }, + "enableAzureMonitoring": { + "value": false + }, + "enableAzureFileShare": { + "value": true + }, + "enableCookieBasedAffinity": { + "value": true + }, + "enableCustomSSL": { + "value": false + }, + "enableDB": { + "value": ${enableDB} + }, + "enableDNSConfiguration": { + "value": false + }, + "jdbcDataSourceName": { + "value": "jdbc/CargoTrackerDB" + }, + "location": { + "value": "${location}" + }, + "ocrSSOPSW": { + "value": "${ocrSSOPSW}" + }, + "ocrSSOUser": { + "value": "${ocrSSOUser}" + }, + "useInternalLB": { + "value": false + }, + "useOracleImage": { + "value": true + }, + "wdtRuntimePassword": { + "value": "${wdtRuntimePassword}" + }, + "wlsImageTag": { + "value": "${wlsImageTag}" + }, + "wlsPassword": { + "value": "${wlsPassword}" + }, + "wlsUserName": { + "value": "${wlsUserName}" + }, + "dbIdentity": { + "value": ${dbIdentity} + } +} \ No newline at end of file diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/arm/nestedtemplates/_pswlessDbTemplate.json b/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/arm/nestedtemplates/_pswlessDbTemplate.json index 84feb48ab..b73945dfe 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/arm/nestedtemplates/_pswlessDbTemplate.json +++ b/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/arm/nestedtemplates/_pswlessDbTemplate.json @@ -163,7 +163,7 @@ "value": "[variables('obj_dbIdentity')]" }, "existingIdentities": { - "value": "[if(equals(reference(resourceId('Microsoft.Compute/virtualMachines',parameters('adminVMName')), '${azure.apiVersionForDeployment}', 'Full').identity.type,'UserAssigned'),reference(resourceId('Microsoft.Compute/virtualMachines',parameters('adminVMName')), '${azure.apiVersionForDeployment}', 'Full').identity.userAssignedIdentities, variables('obj_empty'))]" + "value": "[if(equals(reference(resourceId('Microsoft.Compute/virtualMachines',parameters('adminVMName')), '${azure.apiVersionForVirtualMachines}', 'Full').identity.type,'UserAssigned'),reference(resourceId('Microsoft.Compute/virtualMachines',parameters('adminVMName')), '${azure.apiVersionForVirtualMachines}', 'Full').identity.userAssignedIdentities, variables('obj_empty'))]" }, "location": { "value": "[parameters('location')]" diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/scripts/datasourceConfig-postgresql.sh b/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/scripts/datasourceConfig-postgresql.sh index 056534e64..7c387d58d 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/scripts/datasourceConfig-postgresql.sh +++ b/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/scripts/datasourceConfig-postgresql.sh @@ -65,12 +65,16 @@ function validateInput() then echo _stderr "Please provide PostgreSQL Database URL in the format 'jdbc:oracle:thin:@:/'" exit 1 + else + echo "dsConnectionURL=$dsConnectionURL" fi if [ -z "$dsUser" ]; then echo _stderr "Please provide PostgreSQL Database user name" exit 1 + else + echo "dsUser=$dsUser" fi if [ -z "$dsPassword" ]; @@ -95,6 +99,8 @@ function validateInput() then echo _stderr "Please provide enablePswlessConnection to identity if enabling passwordless connection." exit 1 + else + echo "enablePswlessConnection=$enablePswlessConnection" fi # reset password diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/scripts/installJdbcDrivers.sh b/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/scripts/installJdbcDrivers.sh index 0ee0155a8..625de72b5 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/scripts/installJdbcDrivers.sh +++ b/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/scripts/installJdbcDrivers.sh @@ -67,29 +67,11 @@ function validate_input() { } function install_maven() { - local mavenUrl=$(curl -Ls -o /dev/null -w %{url_effective} ${url4MavenInstaller}) - if [ $? != 0 ]; then - echo_stderr "Failed to get maven download url." - fi - curl -m ${curlMaxTime} --retry ${retryMaxAttempt} -fksL "${mavenUrl}" -o ${mvnInstaller} - if [ $? != 0 ]; then - echo_stderr "Failed to download ${mavenUrl}." - fi - - tar xzvf ${mvnInstaller} -C /u01/app - export MAVEN_HOME=$(find /u01/app -maxdepth 1 -type d -name "apache-maven*") - . $oracleHome/oracle_common/common/bin/setWlstEnv.sh # set JAVA_HOME - export PATH=${MAVEN_HOME}/bin:$PATH - - rm ${mvnInstaller} -f - mvn --version - if [ $? != 0 ]; then - echo_stderr "Failed to install maven." - fi + sudo yum install maven -y } function uninstall_maven() { - sudo rm -f ${MAVEN_HOME} -R + sudo yum remove maven -y } function install_azure_identity_extension() { @@ -244,15 +226,8 @@ export curlMaxTime=120 # seconds export gitUrl4AzureIdentityExtensionPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/azure-identity-extensions.xml" export gitUrl4MySQLDriverPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/mysql-connector-java.xml" export retryMaxAttempt=5 # retry attempt for curl command -export mvnInstaller="apache-maven-bin.tar.gz" -# 2024-09-11 https://github.com/oracle/weblogic-azure/pull/325 -# Increase maintainability by putting URL behind redirector. As of today -# target is https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz -# A better solution would be if Oracle had an employee accessible URL redirector -# service similar to Microsoft's aka.ms. -export url4MavenInstaller="https://aka.ms/wls-offer-maven-download-url" export wlsAdminURL=$wlsAdminHost:$wlsAdminPort validate_input diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-admin/test/scripts/parameters-deploy-template.json b/weblogic-azure-vm/arm-oraclelinux-wls-admin/test/scripts/parameters-deploy-template.json new file mode 100644 index 000000000..4d83ddbc5 --- /dev/null +++ b/weblogic-azure-vm/arm-oraclelinux-wls-admin/test/scripts/parameters-deploy-template.json @@ -0,0 +1,68 @@ +{ + "adminPasswordOrKey": { + "value": "${adminPasswordOrKey}" + }, + "adminUsername": { + "value": "weblogic" + }, + "adminVMName": { + "value": "${adminVMName}" + }, + "virtualNetworkNewOrExisting": { + "value": "${virtualNetworkNewOrExisting}" + }, + "virtualNetworkResourceGroupName": { + "value": "${virtualNetworkResourceGroupName}" + }, + "virtualNetworkName": { + "value": "${virtualNetworkName}" + }, + "subnetName": { + "value": "${subnetName}" + }, + "databaseType": { + "value": "${databaseType}" + }, + "dbPassword": { + "value": "${dbPassword}" + }, + "dbUser": { + "value": "${dbUser}" + }, + "dsConnectionURL": { + "value": "${dsConnectionURL}" + }, + "enablePswlessConnection": { + "value": ${enablePswlessConnection} + }, + "enableDB": { + "value": ${enableDB} + }, + "jdbcDataSourceName": { + "value": "jdbc/WebLogicDB" + }, + "location": { + "value": "${location}" + }, + "skuUrnVersion": { + "value": "${skuUrnVersion}" + }, + "vmSize": { + "value": "Standard_B2ms" + }, + "wlsDomainName": { + "value": "${wlsdomainname}" + }, + "wlsPassword": { + "value": "${wlsPassword}" + }, + "wlsUserName": { + "value": "${wlsUserName}" + }, + "_artifactsLocation": { + "value": "https://raw.githubusercontent.com/${repoPath}/${testbranchName}/weblogic-azure-vm/arm-oraclelinux-wls-admin/src/main/arm/" + }, + "dbIdentity": { + "value": ${dbIdentity} + } +} \ No newline at end of file diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/arm/nestedtemplates/_pswlessDbTemplate.json b/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/arm/nestedtemplates/_pswlessDbTemplate.json index d060897d6..7eb7112ad 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/arm/nestedtemplates/_pswlessDbTemplate.json +++ b/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/arm/nestedtemplates/_pswlessDbTemplate.json @@ -190,7 +190,7 @@ "value": "[variables('obj_dbIdentity')]" }, "existingIdentities": { - "value": "[if(equals(reference(resourceId('Microsoft.Compute/virtualMachines',concat(variables('const_managedVMPrefix'), copyIndex(1))), '${azure.apiVersionForDeployment}', 'Full').identity.type,'UserAssigned'),reference(resourceId('Microsoft.Compute/virtualMachines',concat(variables('const_managedVMPrefix'), copyIndex(1))), '${azure.apiVersionForDeployment}', 'Full').identity.userAssignedIdentities, variables('obj_empty'))]" + "value": "[if(equals(reference(resourceId('Microsoft.Compute/virtualMachines',concat(variables('const_managedVMPrefix'), copyIndex(1))), '${azure.apiVersionForVirtualMachines}', 'Full').identity.type,'UserAssigned'),reference(resourceId('Microsoft.Compute/virtualMachines',concat(variables('const_managedVMPrefix'), copyIndex(1))), '${azure.apiVersionForVirtualMachines}', 'Full').identity.userAssignedIdentities, variables('obj_empty'))]" }, "location": { "value": "[parameters('location')]" diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/scripts/installJdbcDrivers.sh b/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/scripts/installJdbcDrivers.sh index 186876fe1..7daede34a 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/scripts/installJdbcDrivers.sh +++ b/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/scripts/installJdbcDrivers.sh @@ -67,29 +67,11 @@ function validate_input() { } function install_maven() { - local mavenUrl=$(curl -Ls -o /dev/null -w %{url_effective} ${url4MavenInstaller}) - if [ $? != 0 ]; then - echo_stderr "Failed to get maven download url." - fi - curl -m ${curlMaxTime} --retry ${retryMaxAttempt} -fksL "${mavenUrl}" -o ${mvnInstaller} - if [ $? != 0 ]; then - echo_stderr "Failed to download ${mavenUrl}." - fi - - tar xzvf ${mvnInstaller} -C /u01/app - export MAVEN_HOME=$(find /u01/app -maxdepth 1 -type d -name "apache-maven*") - . $oracleHome/oracle_common/common/bin/setWlstEnv.sh # set JAVA_HOME - export PATH=${MAVEN_HOME}/bin:$PATH - - rm ${mvnInstaller} -f - mvn --version - if [ $? != 0 ]; then - echo_stderr "Failed to install maven." - fi + sudo yum install maven -y } function uninstall_maven() { - sudo rm -f ${MAVEN_HOME} -R + sudo yum remove maven -y } function install_azure_identity_extension() { @@ -244,15 +226,7 @@ export curlMaxTime=120 # seconds export gitUrl4AzureIdentityExtensionPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/azure-identity-extensions.xml" export gitUrl4MySQLDriverPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/mysql-connector-java.xml" export retryMaxAttempt=5 # retry attempt for curl command -export mvnInstaller="apache-maven-bin.tar.gz" - -# 2024-09-11 https://github.com/oracle/weblogic-azure/pull/325 -# Increase maintainability by putting URL behind redirector. As of today -# target is https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz -# A better solution would be if Oracle had an employee accessible URL redirector -# service similar to Microsoft's aka.ms. -export url4MavenInstaller="https://aka.ms/wls-offer-maven-download-url" export wlsAdminURL=$wlsAdminHost:$wlsAdminPort validate_input diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-cluster/test/scripts/parameters-deploy-template.json b/weblogic-azure-vm/arm-oraclelinux-wls-cluster/test/scripts/parameters-deploy-template.json new file mode 100644 index 000000000..b28346c71 --- /dev/null +++ b/weblogic-azure-vm/arm-oraclelinux-wls-cluster/test/scripts/parameters-deploy-template.json @@ -0,0 +1,170 @@ +{ + "_artifactsLocation": { + "value": "https://raw.githubusercontent.com/${repoPath}/${testbranchName}/weblogic-azure-vm/arm-oraclelinux-wls-cluster/arm-oraclelinux-wls-cluster/src/main/arm/" + }, + "_artifactsLocationSasToken": { + "value": "" + }, + "location": { + "value": "${location}" + }, + "adminPasswordOrKey": { + "value": "${adminPasswordOrKey}" + }, + "adminUsername": { + "value": "weblogic" + }, + "appGatewayCertificateOption": { + "value": "generateCert" + }, + "authenticationType": { + "value": "password" + }, + "enableDB": { + "value": ${enableDB} + }, + "databaseType": { + "value": "${databaseType}" + }, + "dsConnectionURL": { + "value": "${dsConnectionURL}" + }, + "dbGlobalTranPro": { + "value": "EmulateTwoPhaseCommit" + }, + "dbPassword": { + "value": "${dbPassword}" + }, + "dbUser": { + "value": "${dbUser}" + }, + "enableAppGateway": { + "value": true + }, + "enableCoherence": { + "value": true + }, + "enableCoherenceWebLocalStorage": { + "value": true + }, + "enableCookieBasedAffinity": { + "value": true + }, + "enableDNSConfiguration": { + "value": false + }, + "enablePswlessConnection": { + "value": ${enablePswlessConnection} + }, + "hasDNSZones": { + "value": false + }, + "jdbcDataSourceName": { + "value": "jdbc/WebLogicCafeDB" + }, + "numberOfCoherenceCacheInstances": { + "value": 1 + }, + "numberOfInstances": { + "value": 4 + }, + "skuUrnVersion": { + "value": "${skuUrnVersion}" + }, + "virtualNetworkNewOrExisting": { + "value": "${virtualNetworkNewOrExisting}" + }, + "virtualNetworkResourceGroupName": { + "value": "${virtualNetworkResourceGroupName}" + }, + "virtualNetworkName": { + "value": "${virtualNetworkName}" + }, + "subnetName": { + "value": "${subnetForCluster}" + }, + "subnetForAppGateway": { + "value": "${subnetForAppGateway}" + }, + "addressPrefixes": { + "value": [ + "172.16.6.0/23" + ] + }, + "subnetPrefix": { + "value": "172.16.7.0/28" + }, + "subnetPrefixForAppGateway": { + "value": "172.16.6.0/24" + }, + "vmSize": { + "value": "Standard_B1ms" + }, + "vmSizeSelectForCoherence": { + "value": "Standard_B1ms" + }, + "wlsDomainName": { + "value": "${wlsDomainName}" + }, + "wlsPassword": { + "value": "${wlsPassword}" + }, + "wlsUserName": { + "value": "${wlsUserName}" + }, + "enableCustomSSL": { + "value": false + }, + "dbIdentity": { + "value": ${dbIdentity} + }, + "tagsByResource": { + "value": { + "Microsoft.Network/applicationGateways": { + "Owner": "test" + }, + "Microsoft.Compute/availabilitySets": { + "Owner": "test" + }, + "Microsoft.Resources/deploymentScripts": { + "Owner": "test" + }, + "Microsoft.Network/dnszones": { + "Owner": "test" + }, + "Microsoft.KeyVault/vaults": { + "Owner": "test" + }, + "Microsoft.ManagedIdentity/userAssignedIdentities": { + "Owner": "test" + }, + "Microsoft resources deployment": { + "Owner": "test" + }, + "Microsoft.Network/networkInterfaces": { + "Owner": "test" + }, + "Microsoft.Network/networkSecurityGroups": { + "Owner": "test" + }, + "Microsoft.Network/privateEndpoints": { + "Owner": "test" + }, + "Microsoft.Network/publicIPAddresses": { + "Owner": "test" + }, + "Microsoft.Storage/storageAccounts": { + "Owner": "test" + }, + "Microsoft.Compute/virtualMachines": { + "Owner": "test" + }, + "Virtual machine extension": { + "Owner": "test" + }, + "Microsoft.Network/virtualNetworks": { + "Owner": "test" + } + } + } +} \ No newline at end of file diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/mainTemplate.json b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/mainTemplate.json index a70fdeb8b..32ce5f15c 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/mainTemplate.json +++ b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/mainTemplate.json @@ -845,6 +845,9 @@ "_artifactsLocation": { "value": "[parameters('_artifactsLocation')]" }, + "wlsDomainName": { + "value": "[parameters('wlsDomainName')]" + }, "_artifactsLocationSasToken": { "value": "[parameters('_artifactsLocationSasToken')]" }, diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/nestedtemplates/_installJdbcLibsTemplate.json b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/nestedtemplates/_installJdbcLibsTemplate.json index 225b5242b..68a2cfc29 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/nestedtemplates/_installJdbcLibsTemplate.json +++ b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/nestedtemplates/_installJdbcLibsTemplate.json @@ -122,6 +122,26 @@ "commandToExecute": "[concat('sh',' ',variables('name_scriptInstallJdbcLibs'),' <<< \"',variables('const_wlsHome'),' ',variables('const_wlsDomainPath'),' ',parameters('managedServerPrefix'), copyIndex(1), ' ', parameters('adminVMName'), ' ',variables('const_wlsAdminPort'),' ',parameters('wlsUserName'),' ',base64(parameters('wlsPassword')),' ',parameters('databaseType'),' ',parameters('enablePswlessConnection'), '\"')]" } } + }, + { + "apiVersion": "${azure.apiVersionForVirtualMachines}", + "type": "Microsoft.Compute/virtualMachines/extensions", + "name": "[concat(parameters('adminVMName'), '/newuserscript')]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.Azure.Extensions", + "type": "CustomScript", + "typeHandlerVersion": "2.0", + "autoUpgradeMinorVersion": true, + "settings": { + "fileUris": [ + "[uri(parameters('_artifactsLocationInstallJdbcLibsTemplate'), concat('../scripts/', variables('name_scriptInstallJdbcLibs'), parameters('_artifactsLocationSasToken')))]" + ] + }, + "protectedSettings": { + "commandToExecute": "[concat('sh',' ',variables('name_scriptInstallJdbcLibs'),' <<< \"',variables('const_wlsHome'),' ',variables('const_wlsDomainPath'),' ','admin', ' ', parameters('adminVMName'), ' ',variables('const_wlsAdminPort'),' ',parameters('wlsUserName'),' ',base64(parameters('wlsPassword')),' ',parameters('databaseType'),' ',parameters('enablePswlessConnection'), '\"')]" + } + } } ] } \ No newline at end of file diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/nestedtemplates/_pswlessDbTemplate.json b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/nestedtemplates/_pswlessDbTemplate.json index eecb2a38c..f5d330105 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/nestedtemplates/_pswlessDbTemplate.json +++ b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/nestedtemplates/_pswlessDbTemplate.json @@ -181,7 +181,7 @@ "value": "[variables('obj_dbIdentity')]" }, "existingIdentities": { - "value": "[if(equals(reference(resourceId('Microsoft.Compute/virtualMachines',concat(variables('const_managedVMPrefix'), copyIndex(1))), '${azure.apiVersionForDeployment}', 'Full').identity.type,'UserAssigned'),reference(resourceId('Microsoft.Compute/virtualMachines',concat(variables('const_managedVMPrefix'), copyIndex(1))), '${azure.apiVersionForDeployment}', 'Full').identity.userAssignedIdentities, variables('obj_empty'))]" + "value": "[if(equals(reference(resourceId('Microsoft.Compute/virtualMachines',concat(variables('const_managedVMPrefix'), copyIndex(1))), '${azure.apiVersionForVirtualMachines}', 'Full').identity.type,'UserAssigned'),reference(resourceId('Microsoft.Compute/virtualMachines',concat(variables('const_managedVMPrefix'), copyIndex(1))), '${azure.apiVersionForVirtualMachines}', 'Full').identity.userAssignedIdentities, variables('obj_empty'))]" }, "location": { "value": "[parameters('location')]" diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/scripts/installJdbcDrivers.sh b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/scripts/installJdbcDrivers.sh index 186876fe1..afca85a88 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/scripts/installJdbcDrivers.sh +++ b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/scripts/installJdbcDrivers.sh @@ -67,29 +67,11 @@ function validate_input() { } function install_maven() { - local mavenUrl=$(curl -Ls -o /dev/null -w %{url_effective} ${url4MavenInstaller}) - if [ $? != 0 ]; then - echo_stderr "Failed to get maven download url." - fi - curl -m ${curlMaxTime} --retry ${retryMaxAttempt} -fksL "${mavenUrl}" -o ${mvnInstaller} - if [ $? != 0 ]; then - echo_stderr "Failed to download ${mavenUrl}." - fi - - tar xzvf ${mvnInstaller} -C /u01/app - export MAVEN_HOME=$(find /u01/app -maxdepth 1 -type d -name "apache-maven*") - . $oracleHome/oracle_common/common/bin/setWlstEnv.sh # set JAVA_HOME - export PATH=${MAVEN_HOME}/bin:$PATH - - rm ${mvnInstaller} -f - mvn --version - if [ $? != 0 ]; then - echo_stderr "Failed to install maven." - fi + sudo yum install maven -y } function uninstall_maven() { - sudo rm -f ${MAVEN_HOME} -R + sudo yum remove maven -y } function install_azure_identity_extension() { @@ -244,15 +226,7 @@ export curlMaxTime=120 # seconds export gitUrl4AzureIdentityExtensionPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/azure-identity-extensions.xml" export gitUrl4MySQLDriverPomFile="https://raw.githubusercontent.com/oracle/weblogic-azure/main/weblogic-azure-aks/src/main/resources/mysql-connector-java.xml" export retryMaxAttempt=5 # retry attempt for curl command -export mvnInstaller="apache-maven-bin.tar.gz" - -# 2024-09-11 https://github.com/oracle/weblogic-azure/pull/325 -# Increase maintainability by putting URL behind redirector. As of today -# target is https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz -# A better solution would be if Oracle had an employee accessible URL redirector -# service similar to Microsoft's aka.ms. -export url4MavenInstaller="https://aka.ms/wls-offer-maven-download-url" export wlsAdminURL=$wlsAdminHost:$wlsAdminPort validate_input @@ -275,4 +249,6 @@ if [ $wlsServerName == "admin" ]; then restart_admin_service else restart_managed_servers + echo "Waiting for managed server to start" + sleep 2m fi diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/test/scripts/generate-selfsigned-keystore.sh b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/test/scripts/generate-selfsigned-keystore.sh index 2c81b8995..698648a05 100644 --- a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/test/scripts/generate-selfsigned-keystore.sh +++ b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/test/scripts/generate-selfsigned-keystore.sh @@ -46,5 +46,13 @@ function generate_selfsigned_certificates() { -storetype JKS } +# check if the self-signed certificates already exist +if [ -f "$wlsIdentityKeyStoreFileName" ] && [ -f "$wlsTrustKeyStoreFileName" ] && [ -f "$wlsIdentityRootCertFileName" ]; then + echo "Self-signed certificates already exist. Skipping generation." + exit 0 +else + echo "Self-signed certificates do not exist. Generating new ones." +fi + echo "Starting to generate selfsigned certificates" generate_selfsigned_certificates \ No newline at end of file diff --git a/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/test/scripts/parameters-deploy-template.json b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/test/scripts/parameters-deploy-template.json new file mode 100644 index 000000000..f838c43c1 --- /dev/null +++ b/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/test/scripts/parameters-deploy-template.json @@ -0,0 +1,103 @@ +{ + "adminUsername": { + "value": "weblogic" + }, + "adminPasswordOrKey": { + "value": "$adminPasswordOrKey" + }, + "dnsLabelPrefix": { + "value": "wls" + }, + "wlsDomainName": { + "value": "$wlsdomainname" + }, + "wlsUserName": { + "value": "$wlsusername" + }, + "wlsPassword": { + "value": "$wlspassword" + }, + "managedServerPrefix": { + "value": "$managedServerPrefix" + }, + "maxDynamicClusterSize": { + "value": $maxDynamicClusterSize + }, + "dynamicClusterSize": { + "value": $dynamicClusterSize + }, + "vmSize": { + "value": "Standard_B2ms" + }, + "location": { + "value": "$location" + }, + "skuUrnVersion": { + "value": "$skuUrnVersion" + }, + "_artifactsLocation": { + "value": "https://raw.githubusercontent.com/${repoPath}/${testbranchName}/weblogic-azure-vm/arm-oraclelinux-wls-dynamic-cluster/arm-oraclelinux-wls-dynamic-cluster/src/main/arm/" + }, + "addressPrefixes": { + "value": [ + "172.16.8.0/28" + ] + }, + "subnetPrefix": { + "value": "172.16.8.0/28" + }, + "enableCoherence": { + "value": true + }, + "enableCoherenceWebLocalStorage": { + "value": true + }, + "enableDB": { + "value": ${enableDB} + }, + "databaseType": { + "value": "${databaseType}" + }, + "dsConnectionURL": { + "value": "${dsConnectionURL}" + }, + "dbGlobalTranPro": { + "value": "EmulateTwoPhaseCommit" + }, + "dbPassword": { + "value": "${dbPassword}" + }, + "dbUser": { + "value": "${dbUser}" + }, + "jdbcDataSourceName": { + "value": "jdbc/WebLogicCafeDB" + }, + "enableOHS": { + "value": true + }, + "ohsNMUser": { + "value": "weblogic" + }, + "ohsNMPassword": { + "value": "$wlspassword" + }, + "oracleVaultPswd": { + "value": "$wlspassword" + }, + "uploadedKeyStoreData": { + "value": "${uploadedKeyStoreData}" + }, + "uploadedKeyStorePassword": { + "value": "$wlspassword" + }, + "uploadedKeyStoreType": { + "value": "JKS" + }, + "enablePswlessConnection": { + "value": ${enablePswlessConnection} + }, + "dbIdentity": { + "value": ${dbIdentity} + } +}