How to automate the pipelining in azure devops using rest api - node.js

I would look to automate process of creating build, releases in azure devops. I do understand that rest api's exist. But will they help to automate the process and can this be done in node.js?

yes. Azure Devops do have API. I do not have experiences in node.js.
Docu for Azure DevOps REST API here:
https://learn.microsoft.com/en-us/rest/api/azure/devops/?view=azure-devops-rest-5.0
You may find node.js libraries here:
https://github.com/microsoft/azure-devops-node-api

Can you give a few more details about your desired automation process?
If you mean also the creation of definitions, then I would also have a look into YAML. In the future, there will be few more update especially for the Release Definitions:
https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema
I implemented a Powershell (but not with Node.js) wrapper for the Azure DevOps Api . Here are some code snippets to create a new release:
SET UP CONNECTION
<#
.SYNOPSIS
Sets the environment parameter for the current session so that the commandlets can access Azure DevOps.
#>
function Set-AzureDevOpsEnvironment {
Param(
<# The account name of the Azure DevOps tenant to access. If not set, this is set to "vanstelematics" #>
[Parameter(Mandatory=$true)]
$AzureDevOpsAccountName,
<# The project name of Azure DevOps to work with. If not set, this is set to "ScaledPilotPlatform" #>
[Parameter(Mandatory=$true)]
$AzureDevOpsProjectName,
<# The PAT to access the Azure DevOps REST API. If not set, the function tries to read the PAT from a
textfile called "AzureDevOpsPat.user" either in the current working directory or in the profile
directory of the current user. The textfile must contain only that PAT as plain string. #>
[Parameter(Mandatory=$false)]
$AzureDevOpsPat
)
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
$Script:Verbose = $true
} else {
$Script:Verbose = $false
}
if (!$AzureDevOpsPat) {
$paths = #("AzureDevOpsPat.user", (JOin-Path $env:USERPROFILE "AzureDevOpsPat.user"))
foreach ($path in $paths) {
if (Test-Path $path -ErrorAction SilentlyContinue) {
$AzureDevOpsPat = Get-Content $path
break
}
}
if (!$AzureDevOpsPat) {
Write-Host "AzureDevOpsPat is empty and file AzureDevOpsPat.user not found." -ForegroundColor Red
return
}
}
Write-Host "The Azure DevOps project '$($AzureDevOpsProjectName)' inside the Azure DevOps account '$($AzureDevOpsAccountName)' will be used."
$Script:AzureDevOpsAccountName = $AzureDevOpsAccountName
$Script:AzureDevOpsProjectName = $AzureDevOpsProjectName
$Script:AzureDevOpsPat = $AzureDevOpsPat
}
REST CALLER
function Call-AzureDevOpsApi($Url, $JsonBody, [ValidateSet("GET", "DELETE", "POST", "PUT", "PATCH")]$Method, $ContentType) {
if ($Script:Verbose) {
Write-Host "Calling $($Method) $($Url)"
}
if (!$ContentType) {
$ContentType = "application/json"
}
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(("{0}:{1}" -f "", $Script:AzureDevOpsPat)))
$parameters = #{
Headers = #{Authorization = ("Basic {0}" -f $base64AuthInfo)};
Method = $Method;
Uri = $Url;
}
if ($Method -in #("POST", "PUT", "PATCH")) {
if (!$JsonBody) {
Write-Error "A JsonBody is required for method $($Method)."
return
}
$JsonBodyUtf8 = [Text.Encoding]::UTF8.GetBytes($JsonBody)
$parameters["Body"] = $JsonBodyUtf8
$parameters["ContentType"] = $ContentType
}
$result = Invoke-RestMethod #parameters
return $result
}
function Call-AzureDevOpsApiPost($Url, $JsonBody, [Parameter(Mandatory=$False)][ValidateSet("application/json", "application/json-patch+json")]$ContentType) {
return Call-AzureDevOpsApi -Url $Url -JsonBody $JsonBody -ContentType $ContentType -Method POST
}
function Call-AzureDevOpsApiPut($Url, $JsonBody, [Parameter(Mandatory=$False)][ValidateSet("application/json", "application/json-patch+json")]$ContentType) {
return Call-AzureDevOpsApi -Url $Url -JsonBody $JsonBody -Method PUT
}
function Call-AzureDevOpsApiPatch($Url, $JsonBody, [Parameter(Mandatory=$False)][ValidateSet("application/json", "application/json-patch+json")]$ContentType) {
return Call-AzureDevOpsApi -Url $Url -JsonBody $JsonBody -Method PATCH
}
function Call-AzureDevOpsApiGet($Url, [Parameter(Mandatory=$False)][ValidateSet("application/json", "application/json-patch+json")]$ContentType) {
return Call-AzureDevOpsApi -Url $Url -Method GET
}
function Call-AzureDevOpsApiDelete($Url, [ValidateSet("application/json", "application/json-patch+json")]$ContentType) {
return Call-AzureDevOpsApi -Url $Url -Method DELETE
}
NEW RELEASE
<#
.SYNOPSIS
Creates a new release for a given Release Definition and artifact (p.e. build)
#>
function New-Release {
Param(
<# The id of the release definition to create the release for. #>
[Parameter(Mandatory=$true)]
$ReleaseDefinition,
<# The alias of the artifact of the release definition to create the release for #>
[Parameter(Mandatory=$true)]
$ArtifactAlias,
<# The version of the artifact (p.e. the id of the build)#>
[Parameter(Mandatory=$true)]
$ArtifactVersion,
<# The description/name of the release #>
[Parameter(Mandatory=$true)]
$Description
)
$url = "https://vsrm.dev.azure.com/$($Script:AzureDevOpsAccountName)/$($Script:AzureDevOpsProjectName)/_apis/release/releases?api-version=4.1-preview.6"
$releaseData = #{
"definitionId" = $ReleaseDefinition.id;
"description" = $Description;
"artifacts" = #(
#{
"alias" = $ArtifactAlias;
"instanceReference" = $ArtifactVersion
}
);
"isDraft" = $false;
"reason" = "none";
"manualEnvironments" = $ReleaseDefinition.environments | select -ExpandProperty name
}
$result = Call-AzureDevOpsApiPost -Url $url -JsonBody ($releaseData | ConvertTo-Json -Depth 100)
return $result
}
Hope this gives an idea how to use it.

Related

How to make REST calls to Azure Pipelines from c#

From c# code, I want to call Azure Devops Pipeline Url and get the job/build ids for that url. And then get the result if the job/build succeds/fail.
How to make REST call from c# code my Azure pipelines (I have the pipeline url)?
You can use this sample through HttpClient. Additionally, you can use Microsoft.TeamFoundationServer.Client and BuildHttpClient.GetBuildsAsync: the example is here.
There are 2 ways to do authentication for Azure DevOps API.
Private PAT
Environment Variable: System.AccessToken
For PAT you can review Shamrai Aleksander's code, if you want to call Azure DevOps API in your pipeline, you can conside use System.AccessToken.
Here is Powershell Script for your reference, the field of Authorization is different.
function Http-Request {
param (
[Parameter(Mandatory=$true)]
[string] $Url,
[Parameter(Mandatory=$false)]
[string] $SystemToken
)
if([string]::IsNullOrEmpty($SystemToken)) {
$pat = 'YOUR_PAT'
$username = 'YOUR_USERNAME'
$auth = '{0}:{1}' -f $username, $pat
$bytes = [System.Text.Encoding]::UTF8.GetBytes($auth)
$encoded = [Convert]::ToBase64String($bytes)
$auth = 'Basic ' + $encoded
} else {
$auth = 'Bearer ' + $SystemToken
}
$headers = #{
'Content-Type' = 'application/json'
'Authorization' = $auth
}
Write-Host -ForegroundColor Green 'Http Request:'$Url
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
$response = Invoke-RestMethod -Uri $Url -Method Get -Headers $headers
Write-Host ($reponse | Format-List | Out-String)
return $response
}

Get Key Value Pairs from Azure App Configuration with PowerShell

There aren't any cmdlets in the AZ modules to get key-value pairs from Azure app configuration. Are there any other options besides AZ CLI? Is there a way to interact with service from PowerShell?
There is no PowerShell support to get key-values from App Configuration at this point. Calling Azure CLI in PowerShell is the way to go. The Az.AppConfiguration module only supports management operations (eg., creating an App Configuration store, etc).
The request is tracked in GitHub https://github.com/Azure/AppConfiguration/issues/267.
Hey I'm a bit late to the party but I was searching for the same thing and I ended up created my own solution because the given answer only covers management tasks and not data retrieval.
check out this repo
It can fetch key values and resolve secrets.
Also it can parse referenced keys in the values.
it uses az cli in the background, so you need that installed first.
Azure CLI has a command az appconfig kv list that can be used to list all key-values from App Configuration. More details on the usage and examples can be found here.
Here's my solution using App Configuration connection string for authentication. You're interested in .items property from the returned object. In case of paging, there'll be a next link there as well. For details, see the docs at https://learn.microsoft.com/azure/azure-app-configuration/rest-api-key-value
Keys can contain slash characters, so they need to be URL-encoded using [System.Net.WebUtility]::UrlEncode($Key) when building a $RequestUri.
function Invoke-AppConfigRequest {
param(
[Parameter(Mandatory = $true)] [string] $ConnectionString, # 'Endpoint=...;Id=...;Secret=...'
[Parameter(Mandatory = $true)] [string] $RequestUri, # '/kv?api-version=1.0&key=some-url-encoded-key&label=*'
[Parameter(Mandatory = $false)] [string] $Method = 'GET', # 'GET', 'POST'
[Parameter(Mandatory = $false)] [object] $Body = $null # Accepts [object] to avoid implicit conversion of $null to empty string
)
$ConnectionStringValues = $ConnectionString -split ';' | ForEach-Object { $Tokens = $_ -split '=',2; #{ Key = $Tokens[0]; Value = $Tokens[1] } }
$Endpoint = ($ConnectionStringValues | Where-Object { $_.Key -eq 'Endpoint' }).Value
$Credential = ($ConnectionStringValues | Where-Object { $_.Key -eq 'Id' }).Value
$Secret = ($ConnectionStringValues | Where-Object { $_.Key -eq 'Secret' }).Value
if ([string]::IsNullOrWhitespace($Endpoint) -or [string]::IsNullOrWhitespace($Credential) -or [string]::IsNullOrWhitespace($Secret)) {
throw "Invalid App Configuration connection string"
}
$UtcNow = (Get-Date).ToUniversalTime().ToString('ddd, d MMM yyyy HH:mm:ss \G\M\T')
$EndpointHost = $Endpoint -replace '^https?://(.*)$','$1'
$ContentHash = [Convert]::ToBase64String(
[System.Security.Cryptography.HashAlgorithm]::Create('sha256').ComputeHash(
[System.Text.Encoding]::UTF8.GetBytes($(if ($Body -ne $null) { "$Body" } else { '' }))
)
)
$StringToSign = "$Method`n$RequestUri`n$UtcNow;$EndpointHost;$ContentHash"
$HmacSha256 = New-Object System.Security.Cryptography.HMACSHA256
$HmacSha256.Key = [Convert]::FromBase64String($Secret)
$Signature = [Convert]::ToBase64String(
$HmacSha256.ComputeHash(
[System.Text.Encoding]::UTF8.GetBytes($StringToSign)
)
)
$Headers = #{
'Host' = $EndpointHost;
'x-ms-date' = $UtcNow;
'x-ms-content-sha256' = $ContentHash;
'Accept' = 'application/vnd.microsoft.appconfig.kv+json, application/json, application/problem+json';
'Authorization' = "HMAC-SHA256 Credential=$Credential&SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=$Signature";
}
$Uri = "$Endpoint$RequestUri"
$Response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $Headers -Body $Body
if ($Response.StatusCode -eq 200) {
[System.Text.Encoding]::UTF8.GetString($Response.Content) | ConvertFrom-Json
}
}
Example invocation:
function Get-AppConfigKeyValue {
param(
[Parameter(Mandatory = $true)] [string] $ConnectionString,
[Parameter(Mandatory = $true)] [string] $Key,
[Parameter(Mandatory = $false)] [string] $Label = ''
)
$UrlEncodedKey = [System.Net.WebUtility]::UrlEncode($Key)
$UrlEncodedLabel = [System.Net.WebUtility]::UrlEncode($Label)
# https://learn.microsoft.com/azure/azure-app-configuration/rest-api-key-value
$Method = 'GET'
$ApiVersion = '1.0'
$RequestUri = '/kv'
#if (![string]::IsNullOrWhitespace($UrlEncodedKey)) {
# $RequestUri += "/$UrlEncodedKey" # Strict key/label matching, no support for wildcards like *.
#}
$RequestUri += "?api-version=$ApiVersion"
if (![string]::IsNullOrWhitespace($UrlEncodedKey)) {
$RequestUri += "&key=$UrlEncodedKey" # Key filter, accepts "*" to match all keys.
}
if (![string]::IsNullOrWhitespace($UrlEncodedLabel)) {
$RequestUri += "&label=$UrlEncodedLabel" # Label filter, accepts "*" to match all labels.
} else {
$RequestUri += "&label=%00" # Matches KV without a label.
}
(Invoke-AppConfigRequest -ConnectionString $ConnectionString -RequestUri $RequestUri).items
}
Take a look at the Az.AppConfiguration module. I can't vouch for the quality of it or how complete it is, but it's out there. The Az module doesn't look like it is included as a dependency.
You can download is from the PowerShell Gallery with:
Install-Module -Name Az.AppConfiguration -Repository PSGallery -Scope CurrentUser

Disable AFD Backend Pool's Backend Host with Azure Cli or Azure REST API

Im trying to update an existing backend host of a AFD backend pool to have its status from Enabled to Disabled.
Is there a way to update existing backend host of Front Door backend pools?
currently, i can only see add, list and remove in the following azure front door cli docs:
az network front-door backend-pool backend add
az network front-door backend-pool backend list
az network front-door backend-pool backend remove
Is there one for update?
I've also looked into the Azure REST API docs and have not found an endpoint to update a backend host of AFD backend pools.
I am able to achieve your ask using PowerShell.
Here is the script:
$resourceGroup1 = "frontdoor"
$frontDoor1 = "msrini"
$afd = Get-AzFrontDoor -ResourceGroupName $resourceGroup1 -name $frontDoor1
$loadBalancingSetting1=$afd.LoadBalancingSettings
$afd.BackendPools.backends[0].EnabledState = "Disabled"
$backendpool1=$afd.BackendPools
$frontendEndpoint1 = $afd.FrontendEndpoints
$healthProbeSetting1= $afd.HealthProbeSettings
$routingrule1 = $afd.RoutingRules
$backendpoolsettings1 = $afd.BackendPoolsSetting
Set-AzFrontDoor -Name $frontDoor1 -ResourceGroupName $resourceGroup1 -RoutingRule $routingrule1 -BackendPool $backendpool1 -FrontendEndpoint $frontendEndpoint1 -LoadBalancingSetting $loadBalancingSetting1 -HealthProbeSetting $healthProbeSetting1 -BackendPoolsSetting $backendpoolsettings1
I was able to resolve my issue, the below script requires using azure cli with a logged in service principle.
Param(
[string]$desiredState, #"Enabled" or "Disabled"
[string]$frontDoorName,
[string]$resourceGroupName,
[string]$targetBackendPool,
[string]$targetBackendHost
)
# Get Access Token
$token = az account get-access-token | ConvertFrom-Json
$accessToken = $token.accessToken
$subscriptionId = $token.subscription
$tenantId = $token.tenant
$uri = "https://management.azure.com/subscriptions/$($subscriptionId)/resourceGroups/$($resourceGroupName)/providers/Microsoft.Network/frontDoors/$($frontDoorName)?api-version=2019-05-01"
$headers = #{ "Authorization" = "Bearer $accessToken" }
$contentType = "application/json"
# Get AFD Configuration.
Write-Host "Invoking Azure REST API to get AFD configuration"
$afdConfig = Invoke-WebRequest -method get -uri $uri -headers $headers | ConvertFrom-Json
# Edit AFD Configuration to toggle backend host state
Write-Host "Checking BackendHost: $targetBackendHost In Backend Pool: $targetBackendPool"
foreach ($backendPool in $afdConfig.properties.backendPools) {
if ($backendPool.name -eq $targetBackendPool) {
foreach ($backends in $backendPool.properties.backends) {
if ($backends.address -eq $targetBackendHost) {
$currentState = $backends.enabledState
Write-Host "Current State of $targetBackendHost is $currentState"
if ($currentState -eq $desiredState) {
Write-Host "$targetBackendHost is already in the desired state of $desiredState"
exit
}
$backends.enabledState = $desiredState
Write-Host "$targetBackendHost Updated to $desiredState."
}
}
}
}
$updateRequest = $afdConfig | ConvertTo-Json -Depth 100
# Update AFD Configuration.
Write-Host "Invoking Azure REST API to update AFD configuration"
Invoke-WebRequest -method put -uri $uri -headers $headers -ContentType $contentType -body $updateRequest
# Poll current state until the change has been fully propogated in azure
Write-Host "Polling AFD until update is complete."
do {
$afdConfig = Invoke-WebRequest -method get -uri $uri -headers $headers | ConvertFrom-Json
foreach ($backendPool in $afdConfig.properties.backendPools) {
if ($backendPool.name -eq $targetBackendPool) {
foreach ($backends in $backendPool.properties.backends) {
if ($backends.address -eq $targetBackendHost) {
$currentState = $backends.enabledState
}
}
}
}
Write-Host "$targetBackendHost is currently in $currentState"
Start-Sleep -Seconds 1
} until ($currentState -eq $desiredState)
Write-Host "$targetBackendHost has successfully been updated to $desiredState"
I did it using Powershell
$FrontDoor = Get-AzFrontDoor -ResourceGroupName "FrontDoorResourceGroupName" -Name "FrontDoorName"
$FrontDoor.BackendPools.Backends[0].EnabledState = "Disabled"
Set-AzFrontDoor -InputObject $FrontDoor

Azure WebApp - version controlled configuration/user data deployed separately from app

I've developed an WebApp (API) which is hosted in Azure & uses VSTS for CI/CD/version control.
I'd like to give the customer (owner) of this API the ability to update various configuration/data files under wwwroot, however I'd like those files to be under version control (source of truth - a separate repository to the API source code). Creating/Updating/Deleting one of those files in the repository should cause the file to be uploaded/removed in the WebApp (in a folder under wwwroot).
Modifying (creating/deleting) one of these files should not trigger a full redeployment (of the WebApp)
How can I achieve this? So far I've thought about a VSTS release pipeline for a GIT artefact however I couldn't see a low-friction way to make the changes in the Azure webapp (KUDU API seems a bit complex and heavy-handed)
**EDIT: ** Sample PowerShell script to sync Configuration files in WebApp w/ a build-artefact (PUT/DELETE only invoked when necessary).
# The idea behind this script is to synchronize the configuration files on the server with what's in the repo, only updating files where necessary
param (
[string]$resourceGroupName = "XXX",
[Parameter(Mandatory=$true)][string]$webAppName,
[Parameter(Mandatory=$true)][string]$latestConfigFilesPath
)
function Get-AzureRmWebAppPublishingCredentials($resourceGroupName, $webAppName, $slotName = $null) {
if ([string]::IsNullOrWhiteSpace($slotName)) {
$resourceType = "Microsoft.Web/sites/config"
$resourceName = "$webAppName/publishingcredentials"
} else {
$resourceType = "Microsoft.Web/sites/slots/config"
$resourceName = "$webAppName/$slotName/publishingcredentials"
}
$publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $resourceGroupName -ResourceType $resourceType -ResourceName $resourceName -Action list -ApiVersion 2015-08-01 -Force
return $publishingCredentials
}
function Get-KuduApiAuthorisationHeaderValue($resourceGroupName, $webAppName, $slotName = $null) {
$publishingCredentials = Get-AzureRmWebAppPublishingCredentials $resourceGroupName $webAppName $slotName
return ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))
}
function Get-KuduInode($kuduHref) {
return Invoke-RestMethod -Uri $kuduHref `
-Headers #{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
-Method GET `
-ContentType "application/json"
}
function Get-AllFilesUnderKuduHref($kuduHref) {
$result = #()
$inodes = (Get-KuduInode $kuduHref)
Foreach ($inode in $inodes) {
if ($inode.mime -eq "inode/directory") {
$result += (Get-AllFilesUnderKuduHref $inode.href)
} else {
$result += $inode.href
}
}
return $result
}
function Get-LocalPathForUri([System.Uri]$uri) {
$latestConfigFilesUri = [System.Uri]$latestConfigFilesPath
$localFileUri = [System.Uri]::new($latestConfigFilesUri, $uri)
return $localFileUri.LocalPath
}
function Get-RemoteUri([System.Uri]$uri) {
return [System.Uri]::new($configurationHref, $uri)
}
function Files-Identical($uri) {
$localFilePath = Get-LocalPathForUri $uri
$localFileHash = Get-FileHash $localFilePath -Algorithm MD5
# Download the remote file so that we can calculate the hash. It doesn't matter that it doesn't get cleaned up, this is running on a temporary build server anyway.
$temporaryFilePath = "downloded_kudu_file"
$remoteFileUri = [System.Uri]::new($configurationHref, $uri)
Invoke-RestMethod -Uri $remoteFileUri `
-Headers #{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
-Method GET `
-OutFile $temporaryFilePath `
-ContentType "multipart/form-data"
$remoteFileHash = Get-FileHash $temporaryFilePath -Algorithm MD5
return $remoteFileHash.Hash -eq $localFileHash.Hash
}
function CalculateRelativePath([System.Uri]$needle, [System.Uri]$haystack) {
return $haystack.MakeRelativeUri($needle).ToString();
}
function Put-File([System.Uri]$uri) {
Write-Host "Uploading file $uri"
$localFilePath = Get-LocalPathForUri $uri
$remoteFileUri = Get-RemoteUri $uri
Invoke-RestMethod -Uri $remoteFileUri `
-Headers #{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
-Method PUT `
-InFile $localFilePath `
-ContentType "multipart/form-data"
}
function Delete-File([System.Uri]$uri) {
Write-Host "Deleting file $uri"
$remoteFileUri = Get-RemoteUri $uri
Invoke-RestMethod -Uri $remoteFileUri `
-Headers #{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
-Method DELETE `
}
# Script begins here
$configurationHref = [System.Uri]"https://$webAppName.scm.azurewebsites.net/api/vfs/site/wwwroot/Configuration/"
$kuduApiAuthorisationToken = Get-KuduApiAuthorisationHeaderValue -resourceGroupName $resourceGroupName -webAppName $webAppName
$filenamesOnServer = Get-AllFilesUnderKuduHref $configurationHref $kuduApiAuthorisationToken | % { $configurationHref.MakeRelativeUri($_).OriginalString }
Write-Host "Files currently on server" $filenamesOnServer
$filesCurrentlyInRepo = Get-ChildItem -Path $latestConfigFilesPath -Recurse -File
$filenamesInRepo = $filesCurrentlyInRepo | Select-Object -ExpandProperty FullName | % { CalculateRelativePath $_ $latestConfigFilesPath}
Write-Host "Files currently in repo" $filenamesInRepo
$intersection = $filenamesOnServer | ?{$filenamesInRepo -contains $_}
Write-Host "Intersection: " $intersection
$onlyOnServer = $filenamesOnServer | ?{-Not($filenamesInRepo -contains $_)}
$onlyInRepo = $filenamesInRepo | ?{-Not($filenamesOnServer -contains $_)}
Write-Host "Only on server" $onlyOnServer
Write-Host "Only in repo" $onlyInRepo
Write-Host
Foreach ($uri in $onlyInRepo) {
Put-File $uri
}
Foreach ($uri in $onlyOnServer) {
Delete-File $uri
}
Foreach ($uri in $intersection) {
if (-Not (Files-Identical $uri)) {
Write-Host "Configuration file $uri needs updating"
Put-File $uri
} else {
Write-Host "Configuration file $uri is identical, skipping"
}
}
Write-Host "Sync complete"
With Azure App Service deploy task, you can upload files to app service, but can’t delete files (Uncheck Publish using Web Deploy optioin and specify the folder path in Package or folder input box).
So, the better way is using Kudu API to delete/upload files during build/release.
There is the thread and a blog about using Kudu API:
How to access Kudu in Azure using power shell script
Interacting with Azure Web Apps Virtual File System using PowerShell and the Kudu API

Azure Automation: Calling a URL

I am new to Azure Automation. I want to call a URL and get its HTML once every weekday morning. This is what I have written so far.
workflow Wakeup-Url
{
Param
(
[parameter(Mandatory=$true)]
[String]
$Url
)
$day = (Get-Date).DayOfWeek
if ($day -eq 'Saturday' -or $day -eq 'Sunday'){
exit
}
$output = ""
InlineScript {"$Using:output = (New-Object System.Net.WebClient).DownloadString(`"$Using:Url`");"}
write-output $output
}
Its not giving me the HTML in the output when I test the runbook. Instead what I get in the output pane is:
= (New-Object System.Net.WebClient).DownloadString("https://my.url.com/abc.html");
Your InlineScript is currently just outputting a string containing your script, since you put quotes around the entire expression:
InlineScript {"$Using:output = (New-Object System.Net.WebClient).DownloadString(`"$Using:Url`");"}
This is what you want I think:
$output = InlineScript { (New-Object System.Net.WebClient).DownloadString("$Using:Url"); }
I'm using Azure Runbook scheduler. I used code below to trigger an URL call.
Function OutputStatus($type,$status) {
Write-Output "$type | $status";
}
Function Get-HTTPSStatus($url,$type) {
$HTTPSStatus = Invoke-WebRequest $url -Method Get –UseBasicParsing
if ($HTTPSStatus.StatusCode -eq "200") {
return OutputStatus -type $type -status "Success"
} else {
return OutputStatus -type $type -status "Error"
}
}
Get-HTTPSStatus "http://www.google.com" "Google Website"
Source: https://sharepointyankee.com/2018/01/29/creating-runbooks-in-azure-and-calling-them-from-sharepoint-using-webhooks-and-flow/
This should be a more simple approach than using the Webclient
$output = (Invoke-WebRequest -Uri http://www.google.com -UseBasicParsing).Content

Resources