How to list all running webjobs within an azure subscription using powershell - powershell

I have an azure subscription that has upwards of 200 appServices where around about half of them have Continuous, always on webJobs attached, some also have slots which also have webJobs.
Is there a way to list all webJobs that are inside a subscription? I was originally tring to use powershell to do this but it was getting rather complex and was wondering if anyone knew of an easy way to achieve the above.
It seems like Get-AzureRmWebApp should be able to help but i cant find a way to list the jobs that reside inside the webapps.

I found the command Get-AzureWebsiteJob which is not in the AzureRM family of commandlets. The following script can get the data that I'm looking for:
$groups = get-AzureRmResourceGroup | where{$_.ResourceGroupName -like "*-prod-*"}
foreach($group in $groups){
Write-Host -ForegroundColor Cyan "processing resourceGroup" $group.ResourceGroupName
$webApps = Get-AzureRmWebApp -ResourceGroupName $group.ResourceGroupName
foreach($webApp in $webApps){
write-host -ForegroundColor Yellow $webApp.Name
$job = Get-AzureWebsiteJob -Name $webApp.Name
if($job){
write-host -ForegroundColor DarkYellow $job.JobName
}
$job = Get-AzureWebsiteJob -Name $webApp.Name -Slot staging
if($job){
write-host -ForegroundColor DarkYellow $job.JobName " -staging"
}
}
}
The above does not filter out the running ones from the stopped, but that can be easily added if need be.
Of course you firstly need to be logged into AzureRM and Azure classic
Login-AzureRmAccount
Select-AzureRmSubscription -SubscriptionId <<mySubscriptionId>>
Get-AzureRmContext
Add-AzureAccount
Select-AzureSubscription -SubscriptionId <<mySubscriptionId>>
Get-AzureSubscription -Current
Its a very slow script iterating over this number or AppServices though. Any ideas for speeding it up would be appreciated.

You can do it through the ARM APIs, though you still need to call it on each Web App.
You can get the WebJobs with a GET request to:
https://management.azure.com/subscriptions/subscription-id/resourceGroups/resource-group-name/providers/Microsoft.Web/sites/app-name/webjobs?api-version=2016-03-01
But I doubt this will be any more efficient than what you have since you still need to make a call for every Web App. And you will need to get the access token somehow.
Web Jobs are a property of App Service applications and can't be requested all at once from Azure.

I know it's too late but we can try with Azure CLI too these days.
az webapp webjob triggered list --name MyWebApp --resource-group MyResourceGroup
Additionally, you can query the above result and get the desired information you are looking for
az webapp webjob triggered list --name MyWebApp --resource-group MyResourceGroup --query "[].{Name:name, Schedule:settings.schedule}"

I know it's too late but we can try with Azure CLI too these days.
az webapp webjob triggered list --name MyWebApp --resource-group MyResourceGroup
Additionally, you can query the above result and get the desired information you are looking for
az webapp webjob triggered list --name MyWebApp --resource-group MyResourceGroup --query "[].{Name:name, Schedule:settings.schedule}"
But, again you have to run the above query in the for each loop to fetch the results from all resource groups in the subscription.

Related

How do I update the IP whitelist for a staging slot via Azure Powershell from an Azure DevOps Release Pipeline?

I have an application hosted in Azure, and I use Azure DevOps to manage my build and release pipelines. As part of the release, I warm up the application by making a request to the root url (e.g. https://myapp.azurewebsites.net). In order to make this request I must first make sure the hosted build agent running the deployment has access to that url (or I will get a 403). I have written a short powershell script to achieve this, and put it in an Azure Powershell task. It adds the IP of the build agent to the IpSecurityConfiguration of the app service. So far so good. It works perfectly for apps that are just apps. Where it falls down is when I try to use it against a staging environment. When we release to production we first push the code to a staging slot, then flip it over to live when we've run our tests and made sure everything is good. The powershell script that correctly handles the IpSecurityConfiguration for the app services does not work on the staging slot. To access a staging slot, we use myappname/slots/staging for the variable $(WebApiName), normally it would just be the name of the app service itself. Again, this works perfectly if I run the script from my local environment, it only fails in the pipeline. The code is below:
# Whitelist Azure Agent IPs
$agentIP = Invoke-RestMethod http://ipinfo.io/json | Select -exp ip
Write-Host "Connecting to Azure"
$APIVersion = ((Get-AzureRmResourceProvider -ProviderNamespace Microsoft.Web).ResourceTypes | Where-Object ResourceTypeName -eq sites).ApiVersions[0]
Write-Host "API Version is $APIVersion. Getting web app config for $(WebApiName) in $(ResourceGroupName)"
$WebApiConfig = (Get-AzureRmResource -ResourceType Microsoft.Web/sites/config -ResourceName $(WebApiName) -ResourceGroupName $(ResourceGroupName) -ApiVersion $APIVersion)
Write-Host "Got web app config: $WebApiConfig"
$webIP = [PSCustomObject]#{
ipAddress = "$agentIP/32";
action = "Allow";
tag = 'Default';
priority = 300;
name = $agentIP.ToString();
description = $agentIP.ToString()
}
Write-Host "Adding $agentIP to security restrictions"
$WebApiConfig.Properties.ipSecurityRestrictions += $webIP
Write-Host "Updating security restrictions"
# update app restrictions, do not prompt for confirmation
$result = Set-AzureRmResource -ResourceId $WebApiConfig.ResourceId -Properties $WebApiConfig.Properties -ApiVersion $APIVersion -Force
To muddy the water somewhat, I can get the exact same code to work perfectly with the staging slot locally by changing
$WebApiConfig = (Get-AzureRmResource -ResourceType Microsoft.Web/sites/config -ResourceName $(WebApiName) -ResourceGroupName $(ResourceGroupName) -ApiVersion $APIVersion)
to
$WebApiConfig = (Get-AzureRmResource -ResourceType Microsoft.Web/sites -ResourceName $(WebApiName)/config -ResourceGroupName $(ResourceGroupName) -ApiVersion $APIVersion)
but this doesn't work in the Azure Powershell task. Instead I can't deploy to any environment because the task fails while trying to access IpSecurityRestrictions on the $WebApiConfig object. The exception is "Exception setting "ipSecurityRestrictions": "The property 'ipSecurityRestrictions' cannot be found on this object. Verify that the property exists and can be set."
As I said earlier, if I run the script in exactly this form locally, it works perfectly. Obviously I have to manually replace the variables that come from the build pipeline, but otherwise there is no difference between code that works exactly as I want it to on my local machine and code that fails in the release. You can verify this by swapping out $(WebApiName) for a valid app service name and $(ResourceGroupName) for the resource group that app service is in. I put a line in about halfway down that outputs $WebApiConfig so that I can see what it is, and on my local machine I see a valid object, while in the output of the task I get nothing. The line just says "Got web app config:"
Anyone got any ideas?
I've tried changing the version of powershell used by the task to
match the version I've got.
I've tried using the preview version of the task (v4, otherwise I've been using v3).
I've tried every permutation of /sites/config everywhere I can think of in the call to Get-AzureRmResource (since that was what allowed it to work locally on the slot).
Just one final thing in case anyone wonders. I'm doing it this way instead of whitelisting all the IPs in Microsoft's list (https://www.microsoft.com/en-us/download/confirmation.aspx?id=41653) for two reasons, firstly it's a lot easier to maintain a short list of our own IPs, and secondly there seems to be a bug somewhere in the way Azure handles those CIDR definitions because IPs that are categorically in those ranges are frequently blocked during our deployments even when we have the entire file whitelisted. This way I just add whichever IP is currently being used dynamically to the whitelist, and remove it after we're done. Assuming I can get it to work...
Finally figured out the solution to this. In order to work with slots the resource type has to be subtly different. This line works in an Azure Powershell task:
$WebApiConfig = (Get-AzureRmResource -ResourceType Microsoft.Web/sites/slots/config -ResourceName $(WebApiName) -ResourceGroupName $(ResourceGroupName) -ApiVersion $APIVersion)
Posting in case it helps anyone else with the same issue. I can confirm that the approach I've taken works great in managing access to Azure sites by build agents, and saves a lot of messing around with Microsoft's build agent xml file.

Test-ServiceBusName / Test-EventHub / Function-App

Hi i have a powershell script that can deploy some artifacts to azure. some of the artifacts are
functionapp
functionappservice
eventhubnamespace / eventhubname
storageaccount
I used the below parameters to validate whether storage account and eventhub namespace is available or not.
Test-AzureRmEventHubName
Get-AzureRmStorageAccountNameAvailability
I cannot find any other cmd-lets that does the same thing for other resources like service bus / servicebus queue etc..
Thanks
I can suggest a work around for checking existence
#replace the below condition with get command for the specific resource that you want to check
if(Get-AzureRmEventHub -ResourceGroupName Rgroup -Namespace testnamespace -Name testname -ea SilentlyContinue){
"not found"
}
else{
"found"
}
but if cmdlets like Test-AzureServiceBusName is available then it is definitely better

Still requiring Login-RmAzureAccount even after importing PublishSettings in Azure

I am attempting to login to an Azure account through a PowerShell script by means of making use of a publishsettings file; However, I am still finding that it is requiring me to login to my account using Login-AzureRmAccount, regardless of having those credentials.
My step-by step looks something like this:
Clear out all accounts that may be available:
Get-AzureAccount | ForEach-Object { Remove-AzureAccount $_.ID -Force }
Download the PublishSettings file: Import-AzurePublishSettingsFile –PublishSettingsFile $PublishSettingsFileNameWithPath
Select the Azure subscription using the subscription ID:
Select-AzureRMSubscription -SubscriptionId $SubscriptionId
And finally, create a new resource group in the subscription before deploying it: New-AzureRmResourceGroup -Name $ResourceGroupName -Location $ResourceGroupLocation -Verbose -Force 2>> .\errorCIMS_RG.txt | Out-File .\rgDetailsCIMS_RG.txt
However, this is when an error is thrown: Run Login-AzureRmAccount to login.
Assuming I have the PublishSettings file, and it hasnt expired, why would this be giving back an error?
As Mihail said, we should check Azure PowerShell version first, and install the latest version.
We can run this command to list Azure PowerShell version:
Get-Module -ListAvailable -Name Azure -Refresh
By the way, Import-AzurePublishSettingsFile work for ASM, New-AzureRmResourceGroup is ARM command, so if you want to create resource group, you should Login-AzureRmAccount first.
Note:
The AzureResourceManager module does not support publish settings
files.
More information about Import-AzurePublishSettingsFile, please refer to this link.
I solved this problem by updating to last version of azure powershell cmdlet.
You can find last one here:
https://github.com/Azure/azure-powershell/releases

Stop-AzureWebsiteJob results in "Not Found"

so I've set up a build/deployment in VSO where I want to stop the website and web jobs before deployment (because otherwise files are locked). The powershell script essentially contains:
Stop-AzureWebsite -Name $website # this works, website is stopped after
$jobs = Get-AzureWebsiteJob -Name $website # this works, contains a list of the jobs
Stop-AzureWebsiteJob -Name $website -JobName $job -PassThru
This last line fails, using the names returned from the preceding call I get an unhelpful "Not Found". It's not an account / subscription thing as the preceding lines work happily, does anyone have any ideas?
Thanks in advance
The solution is Remove-AzureWebsiteJob.
Regarding Stop-AzureWebsiteJob command, Starting and stopping Web Jobs is an operation that is only valid on continuous Web Jobs.
Based on the debug log (add -Debug to the command), it is trying to stop a continuous job https://[sitename].scm.azurewebsites.net/api/jobs/continuous/[jobname]/stop.
Regarding your requirement, you can try to stop the job through Kudu API.
There is the sample for using Azure App Service Kudu REST API that you can refer to:
Samples for using the Azure App Service Kudu REST API to programmatically manage files in your site
Related thread: Azure Stop a Triggered Web Job
Here is a simple command:
Invoke-AzResourceAction -ResourceGroupName <RG-NAME> -ResourceType Microsoft.Web/sites/continuouswebjobs -ResourceName <APP-SERVICE/WebJobName> -Action stop -ApiVersion 2018-02-01 -Force

VSTS Azure powershell : No default subscription has been designated

I'm trying to run some azure powershell commands as part of my Visual Studio Team Services build using Azure Resource Manager.
It gives me the following error:
No default subscription has been designated. Use Select-AzureSubscription -Default to set the default subscription.
The commands I'm trying to run:
$website = Get-AzureWebsite | where {$_.Name -eq 'my-website'}
Write-Output ("##vso[task.setvariable variable=DeployUrl;]$website.HostNames")
When I tried to run it locally, I had to call
Add-AzureAccount
Select-AzureRmSubscription -SubscriptionName "Visual Studio Premium with MSDN"
to get it working, but it is not possible in the VSTS build.
UPDATE:
I've configured it to use the azure classic mode instead of resource manager, at it works. I don't think that it is a feasible solution for production as azure classic mode is obsolete.
Since you are using Azure Resource Manager, please check the things below:
Make sure "Azure Resource Manager" service endpoint is added correctly.
Use "Get-AzureRmWebApp" command instead of "Get-AzureWebsite" command just as bmoore mentioned.
I have tested it at my side, it works correctly.
My PowerShell script:
$website = Get-AzureRmWebApp | where {$_.Name -eq 'eddieapp0930'}
Write-Host $website.HostNames
Run from "Azure PowerShell Script" task:
Thank you for your question.
If you are using service manager mode(classic mode), the correct cmdlet is:
Add-AzureAccount
Get-AzureSubscription -SubscriptionName “name” | Select-AzureSubscription
If you are using Resource Manager, the correct cmdlet is:
Login-AzureRmAccount
Get-AzureRmSubscription –SubscriptionName "name" | Select-AzureRmSubscription
or just use -SubscriptionId instead of -SubscriptionName.
More information about ASM and ARM, please refer to the link below:
https://azure.microsoft.com/en-us/documentation/articles/resource-manager-deployment-model/
If you still have questions, welcome to post back here. Thanks.