使用ARM或Powershell脚本部署Web作业

时间:2017-11-28 21:01:48

标签: c# powershell azure azure-web-sites powershell-v2.0

我正在尝试使用PowerShell脚本将Web作业部署到Azure,我们有自己的部署框架,当我从本地计算机部署时,只有拥有管理员或共同管理员权限才能成功部署参与者访问脚本失败。我们的部署框架只有参与者权限,有没有办法用参与者权限部署Web作业,我没有找到任何用于Web作业部署的ARM模板,我在本地有解决方案文件。请给我任何建议 这是我的剧本

`Add-AzureAccount (since web job doesn't have any RM commandlett i am using classic login where All our resource are in RM )
Select-AzureSubscription -SubscriptionName "*************"

$packageSource ="$Global:packageDir/../output\deletelogs\bin"

$destinationSource = "$env:TEMP\DeleteLogsWebjob.zip"

If(Test-path $destinationSource) {Remove-item $destinationSource}

Add-Type -assembly "system.io.compression.filesystem"

[io.compression.zipfile]::CreateFromDirectory($packageSource, $destinationSource) 

$webappname = AzCreateWebAppName "mywebapp$(Get-Random)"

$location =   "EastUs"           #GetCurrentRegion

$resourceGroupName= "*****"           # AzGetResourceGroup

$webjobName = $webappname +"_deletelogsjob"

$jobCollecctionName = $webappname + $webjobName + "JobCollection"

#<### Defining Schedules
#$date = Get-Date 
#$startDate = $date.ToString("MM-dd-yyy HH:mm tt")
#$endDate = $date.AddYears(1).ToString("MM-dd-yyy HH:mm tt")#>

# #Create an App Service plan in Free tier.
New-AzureRmAppServicePlan -Name $webappname -Location $location -ResourceGroupName $resourceGroupName -Tier Basic

## Create a web app.
$webapp = New-AzureRmWebApp -Name $webappname -Location $location -AppServicePlan $webappname -ResourceGroupName $resourceGroupName

###### Create WebJob

$job = New-AzureWebsiteJob -Name $webapp -JobName $webjobName -JobType Triggered -JobFile $destinationSource

$jobCollection = New-AzureRmSchedulerJobCollection -Location $location -JobCollectionName $jobCollecctionName -ResourceGroupName $resourceGroupName

$temp = "$env:TEMP\appsetting.xml"

$file = Get-AzureRMWebAppPublishingProfile -ResourceGroupName $resourceGroupName -Name $webappname -OutputFile $temp -Format WebDeploy


$webSitePassword = ([xml]$file).ChildNodes[0].ChildNodes[0].Attributes[5].Value


$webSiteUserName = ([xml]$file).ChildNodes[0].ChildNodes[0].Attributes[4].Value

$uri = "https://{0}:{1}@{2}.scm.azurewebsites.net/api/triggeredwebjobs/{3}/run" -f $webSiteUserName, $webSitePassword,$webappname, $webjobName

New-AzureRmSchedulerHttpJob -ResourceGroupName $resourceGroupName `
  -JobCollectionName $jobCollection[0].JobCollectionName -JobName "deleteLogsScheduler" -Method POST `
  -URI $uri -StartTime $startDate -Interval 2 -Frequency Minute `
  -EndTime $endDate`

2 个答案:

答案 0 :(得分:1)

您可以使用此blog中的示例。

#Resource details :
$resourceGroupName = "<Resourcegroup name>";
$webAppName = "<WebApp name>";
$Apiversion = 2015-08-01

#Function to get Publishing credentials for the WebApp :
function Get-PublishingProfileCredentials($resourceGroupName, $webAppName){

$resourceType = "Microsoft.Web/sites/config"
$resourceName = "$webAppName/publishingcredentials"
$publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $resourceGroupName -ResourceType 
$resourceType -ResourceName $resourceName -Action list -ApiVersion $Apiversion -Force
   return $publishingCredentials
}

#Pulling authorization access token :
function Get-KuduApiAuthorisationHeaderValue($resourceGroupName, $webAppName){

$publishingCredentials = Get-PublishingProfileCredentials $resourceGroupName $webAppName
return ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f 
$publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))
}

$accessToken = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $webAppname
#Generating header to create and publish the Webjob :
$Header = @{
'Content-Disposition'='attachment; attachment; filename=Copy.zip'
'Authorization'=$accessToken
        }
$apiUrl = "https://$webAppName.scm.azurewebsites.net/api/<Webjob-type>/<Webjob-name>"
$result = Invoke-RestMethod -Uri $apiUrl -Headers $Header -Method put -InFile "<Complete path of the file>\
<filename>.zip" -ContentType 'application/zip' 
#NOTE: Update the above script with the parameters highlighted and run in order to push a new Webjob under the specified WebApp.

对于Kudu授权

$creds = Invoke-AzureRmResourceAction -ResourceGroupName YourResourceGroup -ResourceType Microsoft.Web/sites/config -ResourceName YourWebApp/publishingcredentials -Action list -ApiVersion 2015-08-01 -Force

$username = $creds.Properties.PublishingUserName
$password = $creds.Properties.PublishingPassword
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))

$apiBaseUrl = "https://$($website.Name).scm.azurewebsites.net/api"

$kuduVersion = Invoke-RestMethod -Uri "$apiBaseUrl/environment" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET

答案 1 :(得分:0)

以下几行代码是Power Shell脚本,它使您可以在Web应用程序中部署Webjob。参数通过设置文件参考传递...

#Requires -Version 3.0

Param(
    [string] $settingsFileName = '\Settings\settings.json',
    [boolean] $unitTestMode = $false
    )
$Apiversion = "2015-08-01"
# Define FUNCTIONS

#Check if any requirement is missing
function Test-ParameterSet
{
    param
    (
        [parameter(Mandatory = $true)][System.Object]$settings
    )
    # Loop through the $settings and check no missing setting
    if ($null -eq $applicationFileJson.subscriptions) {throw "Missing subscriptions field in settings file"}
    foreach ($subscription in $applicationFileJson.subscriptions)
    {
        if ($null -eq $subscription.subscriptionId) {throw "Missing subscription Id field in settings file"}
        # Loop through the $settings and check no missing setting
        foreach ($vault in $settings.WorkLoads)
        {
            if ($null -eq $vault.applicationName) {throw "Missing applicationNam in settings file for $($subscription.subscriptionId)"}
            if ($null -eq $vault.environmentName) {throw "Missing environmentName in settings file for $($subscription.subscriptionId)"}
            if ($null -eq $vault.resourceGroupName) {throw "Missing resourceGroupName in settings file for $($subscription.subscriptionId)"}
            if ($null -eq $vault.webAppName) {throw "Missing webAppName in settings file for $($subscription.subscriptionId)"}
            if ($null -eq $vault.Storagerg) {throw "Missing Storagerg in settings file for $($subscription.subscriptionId)"}
            if ($null -eq $vault.webjobname) {throw "Missing webjobname in settings file for $($subscription.subscriptionId)"}
            if ($null -eq $vault.webjobtype) {throw "Missing webjobtype in settings file for $($subscription.subscriptionId)"}
            if ($null -eq $vault.storageAccountName) {throw "Missing storageAccountName in settings file for $($subscription.subscriptionId)"}
            if ($null -eq $vault.container_name) {throw "Missing container_name in settings file for $($subscription.subscriptionId)"}
            If ($vault.webjobtype -eq "triggeredwebjobs")
            {
                if ($null -eq $vault.trigger_type) {throw "Missing trigger_type in settings file for $($subscription.subscriptionId)"}
            }
            }

            If ($vault.webjobtype -eq "triggeredwebjobs" -and $vault.trigger_type -eq "scheduled") 
            {
                 if ($null -eq $vault.schedule) {throw "Missing schedule in settings file for $($subscription.subscriptionId)"}

            If ($vault.webjobtype -eq "continuouswebjobs") 
            {
                 if ($null -eq $vault.continuous_type) {throw "Missing continuous_type in settings file for $($subscription.subscriptionId)"}
            }
    } 
    return $true
} 
}




function Get-KuduApiAuthorisationHeaderValue($resourceGroupName, $webAppName)
{ 
$resourceType = "Microsoft.Web/sites/config"
$resourceName = "$webAppName/publishingcredentials"
$publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $resourceGroupName -ResourceType $resourceType -ResourceName $resourceName -Action list -ApiVersion $Apiversion -Force
return ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))
}


function Publish-webjob
{ 

        [OutputType([String])]
    param
    (
         [parameter(Mandatory = $true)][string]$resourceGroupName,
         [parameter(Mandatory = $true)][string]$webAppName,
         [parameter(Mandatory = $true)][string]$Storagerg,
         [parameter(Mandatory = $true)][string]$webjobname,
         [parameter(Mandatory = $true)][string]$webjobtype,
         [parameter(Mandatory = $true)][string]$storageAccountName,

         [parameter(Mandatory = $true)][string]$container_name,
         [parameter(Mandatory = $true)][string]$settingsFileName,
         [parameter(Mandatory = $true)][string]$i

    )  

    #Check resource group exist
    try {
        $resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -ErrorAction Stop   
    }
    catch {
        $resourceGroup = $null
    }
    if ($null -eq $resourceGroup)
    {
        $message = "Resource group $resourceGroupName not found, deployment stop"
        Write-Verbose $message
        return $message
    }   
        else 
    {
        # Prepare deployment variables
        Write-Verbose "ResourceGroup Found"

        $SettingsJson = Get-JsonParameterSet -settingsFileName $settingsFileName
        $trigger_type = "$($SettingsJson.WorkLoads[$i].trigger_type)"
        Write-Verbose $trigger_type
        $schedule = "$($SettingsJson.WorkLoads[$i].schedule)"
        Write-Verbose $schedule
        $continuous_type = "$($SettingsJson.WorkLoads[$i].continuous_type)"
        Write-Verbose $continuous_type
    }

    # Unlock ResourceGroup
                    Unlock-ResourceGroup $resourceGroupName
                    write-verbose "ResourceGroup Unlocked"

    $accessToken = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $webAppname


    #Get storage account context and storage bolo
    $sa= Get-AzureRmStorageAccount -ResourceGroupName $Storagerg -Name $storageAccountName
    $ctx=$sa.Context
    $blobs = Get-AzureStorageBlob -Container $container_name -Context $ctx
    $webjobtype=$webjobtype+"webjobs"
    $apiUrl = "https://$webAppName.scm.azurewebsites.net/api/$webjobtype/$webjobname"


    #create a folder to save all the files of the container
    $Location=$PSScriptRoot

    New-Item -Path $Location -Name $webjobname -ItemType "directory" -Force
    $folderPath = "$Location"+"\"+$webjobname
    $localFile = $Location+"\"+$webjobname+"\"


    #Generating header to create and publish the Webjob :
    $Header = @{
    "Content-Disposition"="attachment;filename=$($webAppName)"
    "Authorization"=$accessToken
            }
    #Check if the storage container is empty
    If($blobs.Count -eq 0)
    {
        Write-Error  "The storage container is found empty"  
    }

    #get files from container
    foreach ($blob in $blobs)
    {   
        $file=New-TemporaryFile
        $file=Get-AzureStorageBlobContent -Container $container_name -Blob $blob.Name -Context $ctx -Destination $localFile -Force
        $contents = Get-Content $localFile -Raw -ErrorAction:SilentlyContinue
        $f=New-TemporaryFile
        Add-Content $f $contents
    }

    If ($webjobtype -eq "triggeredwebjobs" -and $trigger_type -eq "scheduled") 
    {

            $f = New-TemporaryFile 
            $r="{ ""schedule"" : "+""""+ $schedule+"""" + "}"
            Add-Content $f $r
            $destination=$Location+"\"+$webjobname+"\settings.job"

            Move-Item -Path $f -Destination $destination
    }


    If ($webjobtype -eq "continuouswebjobs") 
    {

        $f = New-TemporaryFile 
        If($continuous_type -eq "singleinstance")
        {
            $c="true"
        }
        If($continuous_type -eq "multipleinstance")
        {
            $c="false"
        }
        $r="{ ""is_singleton"" : " + $c + "}"
        Add-Content $f $r
        $destination=$Location+"\"+$webjobname+"\settings.job"
        Move-Item -Path $f -Destination $destination

    }

    #Archive the files to a zip
    $source = $localFile + "*"
    $wz=$webjobname+".zip"
    $destination = $Location+"\"+$webjobname+"\"+$wz
    Compress-Archive -U -Path $source -DestinationPath $destination

    #Deploying webjobs
    $result = Invoke-RestMethod -Uri $apiUrl -Headers $Header  -Method put -InFile $destination -ContentType 'application/zip'  -ErrorAction Stop 
    Write-Host "Print result " -ForegroundColor Green


    #delete the folder from local mahine
    Remove-Item $folderPath -Force  -Recurse -ErrorAction SilentlyContinue


    # lock ResourceGroup
                #Lock-ResourceGroup $resourceGroupName
                write-verbose "ResourceGroup locked"

    return $result

}



function Publish-Infrastructure
{
param(
        [parameter(Mandatory = $true)][string]$settingsFileName
     )

    $settings = Get-JsonParameterSet -settingsFileName $settingsFileName
    $deploymentIsSucceeded = $true
    $workloadCount = $settings.WorkLoads.Count
    Write-Verbose "workloadCounts: $workloadCount"
    if($workloadCount -ge 1)
    {
        for($i = 0;$i -lt $workloadCount; $i++)
            { 

                $applicationName = $settings.WorkLoads[$i].applicationName
                Write-Verbose "application name: $applicationName"
                $environmentName = $settings.WorkLoads[$i].environmentName
                $applicationFile = "..\SettingsByWorkload\" + "nv_" + $applicationName + ".workload.json"
                $applicationFile = Get-FileFullPath -fileName $applicationFile  -rootPath $PSScriptRoot
                $applicationFileJson = Get-JsonParameterSet -settingsFileName $applicationFile
                Write-Verbose "application file json: $applicationName"
                $null = Test-ParameterSet -settings $settings

                $policyCount = $applicationFileJson.subscriptions.Count
                Write-Verbose "$policyCount"
                if($policyCount -ge 1)
                {  
                    for($j = 0;$j -lt $policyCount; $j++)
                    { 


                        if($applicationFileJson.subscriptions[$j].environmentName -eq $environmentName)
                        {    

                            $subscriptionId = $applicationFileJson.subscriptions[$j].subscriptionId 
                            Write-Verbose "Environment Subscription: $($subscriptionId)"
                            Set-ContextIfNeeded -SubscriptionId $subscriptionId
                            foreach ($webjob in $settings.WorkLoads[$i])
                            {                   
                                                $resourceGroupName = $webjob.resourceGroupName
                                                $webAppName = $webjob.webAppName
                                                $Storagerg = $webjob.Storagerg
                                                $webjobname = $webjob.webjobname
                                                $webjobtype = $webjob.webjobtype
                                                $storageAccountName = $webjob.storageAccountName
                                                $schedule = $webjob.schedule
                                                $container_name = $webjob.container_name
                                                $trigger_type = $webjob.trigger_type
                                                Write-Verbose "Ready to start deployment on environment $EnvironmentName of a webjob in subscription $subscriptionId for resource group: $resourceGroupName"

                                                $result = Publish-webjob ` -resourceGroupName $resourceGroupName `
                                                -webAppName $webAppName `
                                                -Storagerg $Storagerg `
                                                -webjobname $webjobname `
                                                -webjobtype $webjobtype `
                                                -storageAccountName $storageAccountName `
                                                -settingsFileName $settingsFileName `
                                                -container_name $container_name `
                                                -i $i

                            }
                        }
                    }
                }        
            }

    }

        return $true

}


#START OF SCRIPT
if ($unitTestMode)
{
    #do nothing
    Write-Verbose 'Unit test mode, no deployment' -Verbose
}
else 
{
  #Log in Azure if not already done
    try 
    {
        $azureRmContext = Get-AzureRmContext -ErrorAction Stop
    }
    catch 
    {
        $result = Add-AzureRmAccount
        $azureRmContext = $result.Context
    }
    Write-Verbose "Subscription name $($azureRmContext.Subscription.Name)" -Verbose
    $VerbosePreference = 'Continue'

    # Get required templates and setting files. Throw if not found
    $scriptsPath=$PSScriptRoot

    $scriptsPath = Split-Path -Path $scriptsPath -Parent  


    $SettingsPath = Join-Path $scriptsPath $settingsFileName

    $settingsFileName = $SettingsPath



    Write-Verbose "Settings file name $($settingsFileName)" -Verbose

    # Deploy infrastructure
    return Publish-Infrastructure `
        -settingsFileName $settingsFileName `

# END of script
}