Azure / azure-sdk

This is the Azure SDK parent repository and mostly contains documentation around guidelines and policies as well as the releases for the various languages supported by the Azure SDK.
http://azure.github.io/azure-sdk
MIT License
477 stars 295 forks source link

Automate Azure WebJobs testing #902

Closed joshfree closed 5 months ago

joshfree commented 4 years ago

Tracking issue for step-by-step instructions for how to manually run e2e tests for Azure WebJobs hosted environments for each of the azure-sdk-for-* languages. This issue will be used by our Vendor team for manually running tests in this scenario, and will be tracked on the EngSys backlog for eventual automation.

Assigning to @g2vinay who will create the initial instructions specific to Java Azure SDKs. Other SDK languages will be appended to this issue as further comments.

g2vinay commented 4 years ago

We need to automate the way we run tests. The steps to run MSI tests in Azure Web Jobs for the identity component are as follows:

prerequisite tools

Azure resources

This test requires instances of these Azure resources:

Initial Setup:

PLEASE NOTE: This setup is Java specific since it installs the Java & Maven environments. Other languages will have a different set up.

Set environment variables to simplify copy-pasting

Create resources

  1. In a powershell with Azure CLI, create the resource group. This step is optional, skip if resource group already exists.

    az group create -n $RESOURCE_GROUP -l $LOCATION
  2. Create the app service plan

    az appservice plan create -n $PLAN_NAME -g $RESOURCE_GROUP -l $LOCATION --sku $PLAN_SKU
  3. Create a web app

    az webapp create -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP --plan $PLAN_NAME
  4. Enable System assigned identity on the web app.

    az webapp identity assign --name $APP_NAME_SYSTEM_ASSIGNED --resource-group $RESOURCE_GROUP
  5. Create a user identity for the second web app:

    az identity create -n $MANAGED_IDENTITY_NAME -g $RESOURCE_GROUP -l $LOCATION
  6. create the second web app:

    az webapp create -n $APP_NAME_USER_ASSIGNED -g $RESOURCE_GROUP --plan $PLAN_NAME
  7. Assign the user Identity from Step 5 to the second web app.

    • Login to portal
    • Go to the second web app resource
    • Select the Identity tab under Settings,
    • Click on User assigned
    • Click on Add
    • Select your subscription
    • Search for the user Identity with name $MANAGED_IDENTITY_NAME and select it from the list.
  8. Create a Key Vault:

    az keyvault create  -n $KEY_VAULT_NAME -g $RESOURCE_GROUP

Get the principal ID for the Web app with system assigned identity:

$principalId=az webapp show -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP --query "identity.principalId"
$principalId=$principalId.Replace('"', '')

Allow the Web app with system assigned identity to access the key vault secrets:

az keyvault set-policy -n $KEY_VAULT_NAME --object-id $principalId --secret-permissions get list

Get the principal ID for the second Web app with user assigned identity:

$principalId=az identity show -n $MANAGED_IDENTITY_NAME -g $RESOURCE_GROUP --query "principalId"
$principalId=$principalId.Replace('"', '')

Allow the Web app with user assigned identity to access the key vault secrets:

az keyvault set-policy -n $KEY_VAULT_NAME --object-id $principalId --secret-permissions get list

Add a secret called "secret":

az keyvault secret set --vault-name $KEY_VAULT_NAME -n secret --value "Secret value"

Build the executable jar

The executable jar holds the logic to run tests. will be different per language.

  1. clone azure-sdk-for-java-repo
  2. Install Build tools
    mvn clean install -Dgpg.skip -f eng\code-quality-reports\pom.xml
  3. Install Key vault libraries(paths are relative to the root of the repo)
    mvn clean install -Dgpg.skip -Dcheckstyle.skip -Dspotbugs.skip -Drevapi.skip -Dmaven.javadoc.skip=true -DskipTests -f sdk/keyvault/pom.service.xml 
  4. Build the jar with dependencies
    mvn clean package -Dpackage-with-dependencies -f sdk\e2e\pom.xml

    sdk\e2e\target will contain an executable with jar with dependencies.

Package, Deploy and run tests

Run System Assigned Web Job Test

  1. Create a directory systemAssignedTest

    mkdir systemAssignedTest
  2. Copy executable jar - azure-e2e-1.0.0-beta.1-jar-with-dependencies.jar from sdk\e2e\target to the systemAssignedTest directory.

  3. Setup SystemAssignedTest Executable:

    $content="set AZURE_VAULT_URL=https://$KEY_VAULT_NAME.vault.azure.net"
    $content += "`r`n"
    $content +="set AZURE_WEBJOBS_TEST_MODE=system"
    $content += "`r`n"
    $content +="set  AZURE_IDENTITY_TEST_PLATFORM=webjobs"
    $content += "`r`n"
    $content +="java -jar azure-e2e-1.0.0-beta.1-jar-with-dependencies.jar"
    Set-Content -Value $content -Path '<Relative-path-to-systemAssignedTest-directory>\run.bat'

Create system assigned test web job deployment file

$netFrameworkVersion="v<YOUR-DOT-NET-FRAMEWORK-VERSION>"
Add-Type -Path "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\$netFrameworkVersion\System.IO.Compression.FileSystem.dll"

$systemAssignedWebJobzip = "<OUTPUT_PATH>\systemwebjob.zip"
if(Test-path $systemAssignedWebJobzip) {Remove-item $systemAssignedWebJobzip}
[io.compression.zipfile]::CreateFromDirectory("<path-to-systemAssignedTest-directory>", $systemAssignedWebJobzip)
  1. Build user credentials for deployment
    $user = az webapp deployment list-publishing-profiles -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP `
    --query "[?publishMethod=='MSDeploy'].userName" -o tsv
$pass = az webapp deployment list-publishing-profiles -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP `
    --query "[?publishMethod=='MSDeploy'].userPWD" -o tsv
$creds = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($creds))
$basicAuthValue = "Basic $encodedCreds"

Deploy the system assigned web job

$ZipHeaders = @{
    Authorization = $basicAuthValue
    "Content-Disposition" = "attachment; filename=run.cmd"
}

# upload the system assigned job using the Kudu WebJobs API
Invoke-WebRequest -Uri https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/Systemassignedjob -Headers $ZipHeaders `
    -InFile $systemAssignedWebJobzip -ContentType "application/zip" -Method Put
  1. Run the Web Job Test:: Configure auth header
    $Headers = @{
    Authorization = $basicAuthValue
    }

Run the system assigned web job

$resp = Invoke-WebRequest -Uri "https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/Systemassignedjob/run?arguments=eggs bacon" -Headers $Headers `
    -Method Post -ContentType "multipart/form-data"

Print the web job output log: Wait for 30 -40 seconds for job to execute, to get the full log. You can run the below command multiple times too, to see the progress of the job.

if ($resp.RawContent -match "\nLocation\: (.+)\n")
{
    $historyLocation = $matches[1]
    $hist = Invoke-RestMethod -Uri $historyLocation -Headers $Headers -Method Get
    # $hist has status, start_time, end_time, duration, error_url etc
    # get the logs from output_url
    Invoke-RestMethod -Uri $hist.output_url -Headers $Headers -Method Get
}

Success Output: image

Run User Assigned Web job Test

  1. Create a directory userAssignedTest

    mkdir userAssignedTest
  2. Copy executable jar - azure-e2e-1.0.0-beta.1-jar-with-dependencies.jar from sdk\e2e\target to the userAssignedTest directory.

  3. Get the client id of the user assigned identity

    $clientId=az identity show -n $MANAGED_IDENTITY_NAME -g $RESOURCE_GROUP --query "clientId"
    $clientId=$clientId.Replace('"', '')
  4. Setup UserAssignedTest Executable: In powershell, run following:

    $content="set AZURE_VAULT_URL=https://$KEY_VAULT_NAME.vault.azure.net"
    $content += "`r`n"
    $content +="set AZURE_WEBJOBS_TEST_MODE=user"
    $content += "`r`n"
    $content +="set AZURE_CLIENT_ID=$clientId"
    $content += "`r`n"
    $content +="set  AZURE_IDENTITY_TEST_PLATFORM=webjobs"
    $content += "`r`n"
    $content +="java -jar azure-e2e-1.0.0-beta.1-jar-with-dependencies.jar"
    Set-Content -Value $content -Path '<Relative-Path-To-userAssignedTest-directory>\run.bat'

    Create user assigned test web job deployment file

    
    $netFrameworkVersion="v<YOUR-DOT-NET-FRAMEWORK-VERSION>"
    Add-Type -Path "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\$netFrameworkVersion\System.IO.Compression.FileSystem.dll"

$userAssignedWebJobzip = "\userwebjob.zip" if(Test-path $userAssignedWebJobzip) {Remove-item $userAssignedWebJobzip} [io.compression.zipfile]::CreateFromDirectory("", $userAssignedWebJobzip)


5. Build user credentials for deployment
```powershell
$user = az webapp deployment list-publishing-profiles -n $APP_NAME_USER_ASSIGNED -g $RESOURCE_GROUP `
    --query "[?publishMethod=='MSDeploy'].userName" -o tsv
$pass = az webapp deployment list-publishing-profiles -n $APP_NAME_USER_ASSIGNED -g $RESOURCE_GROUP `
    --query "[?publishMethod=='MSDeploy'].userPWD" -o tsv
$creds = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($creds))
$basicAuthValue = "Basic $encodedCreds"

Deploy the system assigned web job

$ZipHeaders = @{
    Authorization = $basicAuthValue
    "Content-Disposition" = "attachment; filename=run.cmd"
}

# upload the user assigned job using the Kudu WebJobs API
Invoke-WebRequest -Uri https://$APP_NAME_USER_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/Userassignedjob -Headers $ZipHeaders `
    -InFile $userAssignedWebJobzip -ContentType "application/zip" -Method Put
  1. Run the User assigned Web Job Test:: Configure auth header

    $Headers = @{
    Authorization = $basicAuthValue
    }

    Run the user assigned web job

    $resp = Invoke-WebRequest -Uri "https://$APP_NAME_USER_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/Userassignedjob/run?arguments=eggs bacon" -Headers $Headers `
    -Method Post -ContentType "multipart/form-data"

Print the web job output log: Wait for 30 -40 seconds for job to execute, to get the full log. You can run the below command multiple times too, to see the progress of the job.

if ($resp.RawContent -match "\nLocation\: (.+)\n")
{
    $historyLocation = $matches[1]
    $hist = Invoke-RestMethod -Uri $historyLocation -Headers $Headers -Method Get
    # $hist has status, start_time, end_time, duration, error_url etc
    # get the logs from output_url
    Invoke-RestMethod -Uri $hist.output_url -Headers $Headers -Method Get
}

Success output: image

XuGuang-Yao commented 4 years ago

Hi @g2vinay ,

I am following above steps to do java E2E test. My suggestion as below. Please correct me if I miss anything.

1.Since the /keyvault /pom.service.xml file has been deleted by this PR, we need change sdk /keyvault/pom.service.xml to sdk/keyvault /pom.xml in Build the executable jar step.

2.Commands with .skip fails with below error. image

So we need to inclose Dgpg.skip with quotation marks.

mvn clean install -"Dgpg.skip"  -f eng\code-quality-reports\pom.xml
mvn clean install -"Dgpg.skip" -"Dcheckstyle.skip" -"Dspotbugs.skip" -"Drevapi.skip" -"Dmaven.javadoc.skip=true" -DskipTests -f sdk/keyvault/pom.xml
sophiajt commented 4 years ago

For JavaScript:

Instructions

Follow these instructions using PowerShell.

set environment variables to simplify copy-pasting

App Service

Create the app service plan

az appservice plan create -n $PLAN_NAME -g $RESOURCE_GROUP -l $LOCATION --sku $PLAN_SKU

Create a web app

az webapp create -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP --plan $PLAN_NAME -r '"node|10.15"'

Enable System assigned identity on the web app.

az webapp identity assign --name $APP_NAME_SYSTEM_ASSIGNED --resource-group $RESOURCE_GROUP

Resource Group

az group create -n $RESOURCE_GROUP --location westus2

Managed Identity

Create the managed identity:

az identity create -g $RESOURCE_GROUP -n $MANAGED_IDENTITY_NAME

Save its clientId, id (ARM URI), and principalId (object ID) for later:

$MANAGED_IDENTITY_PRINCIPAL_ID=az identity show -g $RESOURCE_GROUP -n $MANAGED_IDENTITY_NAME --query principalId -o tsv

Key Vault

Create the Vault:

az keyvault create -g $RESOURCE_GROUP -n $KEY_VAULT_NAME --sku standard

Add an access policy for the managed identity:

az keyvault set-policy -n $KEY_VAULT_NAME --object-id $MANAGED_IDENTITY_PRINCIPAL_ID --secret-permissions set delete

Web App

az webapp config appsettings set -g $RESOURCE_GROUP -n $APP_NAME_SYSTEM_ASSIGNED --settings KEY_VAULT_NAME=$KEY_VAULT_NAME

Build the webapp

git clone https://github.com/azure/azure-sdk-for-js --single-branch --branch master --depth 1
cd azure-sdk-for-js\sdk\identity\identity\test\manual-integration\webjobs\App_Data\jobs\triggered\AzureTestJob

Install the requirements:

npm install

Build the job:

tsc index.ts

Zip the App_Data directory, and all its contents, into "AzureTestJob.zip"

Upload the job

$user = az webapp deployment list-publishing-profiles -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP `
    --query "[?publishMethod=='MSDeploy'].userName" -o tsv

$pass = az webapp deployment list-publishing-profiles -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP `
    --query "[?publishMethod=='MSDeploy'].userPWD" -o tsv

$creds = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($creds))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
    Authorization = $basicAuthValue
}

Invoke-WebRequest -Uri https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/zipdeploy -Headers $Headers -InFile .\AzureTestJob.zip -ContentType "multipart/form-data" -Method Post

Trigger the job

az webapp webjob triggered run -w AzureTestJob -g $RESOURCE_GROUP -n $APP_NAME_SYSTEM_ASSIGNED

Test the job completed successfully

az keyvault secret show -n "secret-name" --vault-name "$($KEY_VAULT_NAME)"

Delete Azure resources

After running tests, delete the resources provisioned earlier:

az group delete -n $RESOURCE_GROUP -y --no-wait
XuGuang-Yao commented 4 years ago

Hi @jonathandturner,

I am following above steps to do JS E2E test. My suggestion as below. Please correct me if I miss anything.

If I run node install , below error will occur. Do you mean npm install?

image

Anyway, I tried to run the npm install instead of node install but another error occured.

image

Could you please help to check the test steps and update them?

sophiajt commented 4 years ago

@XuGuang-Yao - apologies, yes, it should be npm install. That was a typo.

I've updated the instructions, please try again.

XuGuang-Yao commented 4 years ago

@jonathandturner , -Thanks you for your quick reply.

As I mentioned before, I have tried to run the npm install instead of node install . Please refer to my previous comment for result. I believe the command won't work until we figure out how to install libsecret in this test scenario. (related to keytar issue)

XuGuang-Yao commented 4 years ago

@jonathandturner ,

I am following the JS instrucation step by step to do E2E test against May release.

After exexuting all commands, I got the below result. image

It looks like the test code didn't run since there is no a secret named 'secret-name'.I tried to repeat the steps 3,4 times but getting the same result.

Did I miss anything?

kurtzeborn commented 4 years ago

As @joshfree said in the initial description, this issue is being used by the vendors to track running the tests manually, so putting "Client" label back on this issue. I've opened https://github.com/Azure/azure-sdk/issues/1539 to track adding WebJob support on the EngSys backlog.

joshfree commented 4 years ago

Closing since #1539 is tracking the EngSys work separately. There's no remaining work here, until #1539 is complete.

joshfree commented 4 years ago

Re-opening issue; @danieljurek will handle #1539 and once #1539 is resolved then @g2vinay can help onboard #902 with Java first, and the rest of the languages next.

catalinaperalta commented 3 years ago

Steps to test for Golang:

Prerequisites

Azure resources

This test requires instances of these Azure resources:

Initial Setup

Set the following environment variables to simplify copy-pasting

In a powershell with Azure CLI, create the resource group. This step is optional, skip if resource group already exists.

az group create -n $RESOURCE_GROUP -l $LOCATION

Create the app service plan

az appservice plan create -n $PLAN_NAME -g $RESOURCE_GROUP -l $LOCATION --sku $PLAN_SKU

Create a web app

az webapp create -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP --plan $PLAN_NAME

Enable System assigned identity on the web app.

az webapp identity assign --name $APP_NAME_SYSTEM_ASSIGNED --resource-group $RESOURCE_GROUP

Create a user identity for the second web app:

az identity create -n $MANAGED_IDENTITY_NAME -g $RESOURCE_GROUP -l $LOCATION

Create the second web app:

az webapp create -n $APP_NAME_USER_ASSIGNED -g $RESOURCE_GROUP --plan $PLAN_NAME

Assign the user Identity from Step 5 to the second web app.

  1. Login to portal
  2. Go to the second web app resource
  3. Select the Identity tab under Settings,
  4. Click on User assigned
  5. Click on Add
  6. Select your subscription
  7. Search for the user Identity with name $MANAGED_IDENTITY_NAME and select it from the list.

Build the webapp

Download the Go SDK:

git clone https://github.com/Azure/azure-sdk-for-go.git

Go to the samples folder

cd azure-sdk-for-go/sdk/samples/azidentity/manual-tests/managed_identity

Build the project

go build

This should generate a main.exe which should be compressed into a .zip file. The following commands assume that the compressed folder is called main.zip.

Execute the following commands to set up for the headers that will be sent with the requests

$user = az webapp deployment list-publishing-profiles -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP --query "[?publishMethod=='MSDeploy'].userName" -o tsv
$pass = az webapp deployment list-publishing-profiles -n $APP_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP --query "[?publishMethod=='MSDeploy'].userPWD" -o tsv
$creds = "$($user):$($pass)" 
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($creds))
$basicAuthValue = "Basic $encodedCreds" 

Set the header variables that will be used when uploading and triggering the jobs

$Headers = @{
     Authorization = $basicAuthValue
}
$ZipHeaders = @{
     Authorization = $basicAuthValue
     "Content-Disposition" = "attachment; filename=main.exe"
}

Upload the job

Invoke-WebRequest -Uri https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/WebJob1 -Headers $ZipHeaders -InFile main.zip -ContentType "application/zip" -Method Put -UseBasicParsing

Trigger the job

$resp = Invoke-WebRequest -Uri "https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/Webjob1/run?arguments=eggs bacon" -Headers $Headers  -Method Post -ContentType "multipart/form-data" -UseBasicParsing

You can run echo $resp to see if the webjob was accepted with a 202 status.

Check the results

To get information about the webjob that was triggered run the following command until you see that it changes status from Running to Success.

$resp = Invoke-WebRequest -Uri "https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/WebJob1" -Headers $Headers  -Method Get -ContentType "multipart/form-data" -UseBasicParsing

To see the response run echo $resp

Once you see that the request was successful, run the following command:

echo $resp.Content

Copy the url under output_url and paste it in the browser. Successful output should look similar to:

[10/22/2020 21:27:14 > 636b58: SYS INFO] Status changed to Initializing
[10/22/2020 21:27:14 > 636b58: SYS INFO] Job directory change detected: Job file 'main.exe' timestamp differs between source and working directories.
[10/22/2020 21:27:15 > 636b58: SYS INFO] Run script 'main.exe' with script host - 'WindowsScriptHost'
[10/22/2020 21:27:15 > 636b58: SYS INFO] Status changed to Running
[10/22/2020 21:27:17 > 636b58: INFO] Calling GetToken()...
[10/22/2020 21:27:17 > 636b58: INFO] Success! Token received.
[10/22/2020 21:27:17 > 636b58: SYS INFO] Status changed to Success
Menghua1 commented 1 year ago

Hi @g2vinay Following above steps, when run system Assigned Web job Test about java E2E, we encountered an error after executing the following command:

$resp = Invoke-WebRequest -Uri "https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/Systemassignedjob/run?arguments=eggs bacon" -Headers $Headers -Method Post -ContentType "multipart/form-data"

if ($resp.RawContent -match "\nLocation\: (.+)\n")
{
    $historyLocation = $matches[1]
    $hist = Invoke-RestMethod -Uri $historyLocation -Headers $Headers -Method Get
    # $hist has status, start_time, end_time, duration, error_url etc
    # get the logs from output_url
    Invoke-RestMethod -Uri $hist.output_url -Headers $Headers -Method Get
}

The detailed error information is as follows: image

Could you help to check and resolve the error?

v-jiaodi commented 1 year ago

@catalinaperalta @chlowell Following above steps, encountered some issues about Golang E2E Test. Firstly, the following command, managed_identity does not exist and should be updated to managed-identity. image

Then, when run go build get error message as follow: image

Could you help to check and resolve the error?

Menghua1 commented 1 year ago

Hi @g2vinay,@jntrnr Following above steps, encountered some issues about java and JavaScript E2E Test. we encountered an error after executing the command:

Invoke-WebRequest -Uri [https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/triggeredwebjobs/Systemassignedjob](https://%24app_name_system_assigned.scm.azurewebsites.net/api/triggeredwebjobs/Systemassignedjob) -Headers $ZipHeaders -InFile $systemAssignedWebJobzip -ContentType "application/zip" -Method Put

or

Invoke-WebRequest -Uri "[https://$APP_NAME_SYSTEM_ASSIGNED.scm.azurewebsites.net/api/zipdeploy](https://%24app_name_system_assigned.scm.azurewebsites.net/api/zipdeploy)" -Headers $Headers -InFile .\AzureTestJob.zip -ContentType "multipart/form-data" -Method Post

The error messages of java and JavaScript are the same, and the detailed error messages are as follows: image

Could you help to check and resolve the error?

github-actions[bot] commented 5 months ago

Hi @joshfree, we deeply appreciate your input into this project. Regrettably, this issue has remained inactive for over 2 years, leading us to the decision to close it. We've implemented this policy to maintain the relevance of our issue queue and facilitate easier navigation for new contributors. If you still believe this topic requires attention, please feel free to create a new issue, referencing this one. Thank you for your understanding and ongoing support.

v-xuto commented 5 months ago

@joshfree This issue has been closed. Do we need to continue testing this Automate Azure WebJobs testing?