Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Users/pragupta/azurepwrshelltask #3175

Merged
merged 3 commits into from
Dec 5, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions Tasks/AzurePowerShell/AzurePowerShell.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ Trace-VstsEnteringInvocation $MyInvocation
Import-VstsLocStrings "$PSScriptRoot\Task.json"

# Get inputs.
$scriptPath = Get-VstsInput -Name ScriptPath -Require
$scriptType = Get-VstsInput -Name ScriptType -Require
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when script type is filepath, then shouldn't ScriptPath be required? i.e. Get-VstsInput -Name ScriptPath -Require

similar thing for inline scenario

$scriptPath = Get-VstsInput -Name ScriptPath
$scriptInline = Get-VstsInput -Name AzurePowerShellInline
$scriptArguments = Get-VstsInput -Name ScriptArguments

# Validate the script path and args do not contains new-lines. Otherwise, it will
# break invoking the script via Invoke-Expression.
if ($scriptPath -match '[\r\n]') {
throw (Get-VstsLocString -Key InvalidScriptPath0 -ArgumentList $scriptPath)
if ($scriptType -eq "FilePath") {
if ($scriptPath -match '[\r\n]') {
throw (Get-VstsLocString -Key InvalidScriptPath0 -ArgumentList $scriptPath)
}
}

if ($scriptArguments -match '[\r\n]') {
Expand All @@ -20,6 +24,14 @@ Import-Module $PSScriptRoot\ps_modules\VstsAzureHelpers_
Initialize-Azure

# Trace the expression as it will be invoked.
If ($scriptType -eq "InlineScript") {
$tempFileName = [guid]::NewGuid().ToString() + ".ps1";
$scriptPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), $tempFileName);
($scriptInline | Out-File $scriptPath)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should try/finally and best-effort cleanup this temp file. here is what the agent does for the powershell task. it creates a warning issue if the file fails to delete for some reason.


Write-Host "tempFile= $scriptPath"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add localized string here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like debug messaging to me. consider the write-verbose instead.

}

$scriptCommand = "& '$($scriptPath.Replace("'", "''"))' $scriptArguments"
Remove-Variable -Name scriptPath
Remove-Variable -Name scriptArguments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
"loc.friendlyName": "Azure PowerShell",
"loc.helpMarkDown": "[More Information](https://go.microsoft.com/fwlink/?LinkID=613749)",
"loc.description": "Run a PowerShell script within an Azure environment",
"loc.instanceNameFormat": "Azure PowerShell script: $(ScriptPath)",
"loc.instanceNameFormat": "Azure PowerShell script: $(ScriptType)",
"loc.input.label.ConnectedServiceNameSelector": "Azure Connection Type",
"loc.input.label.ConnectedServiceName": "Azure Classic Subscription",
"loc.input.help.ConnectedServiceName": "Azure Classic subscription to configure before running PowerShell",
"loc.input.label.ConnectedServiceNameARM": "Azure RM Subscription",
"loc.input.help.ConnectedServiceNameARM": "Azure Resource Manager subscription to configure before running PowerShell",
"loc.input.label.ScriptType": "Script Type",
"loc.input.help.ScriptType": "Type of the script: File Path or Inline Script",
"loc.input.label.ScriptPath": "Script Path",
"loc.input.help.ScriptPath": "Path of the script. Should be fully qualified path or relative to the default working directory.",
"loc.input.label.AzurePowerShellInline": "Inline AzurePowerShell Script",
"loc.input.help.AzurePowerShellInline": "Enter the AzurePowerShell script to execute.",
"loc.input.label.ScriptArguments": "Script Arguments",
"loc.input.help.ScriptArguments": "Additional parameters to pass to PowerShell. Can be either ordinal or named parameters.",
"loc.messages.InvalidScriptArguments0": "Invalid script arguments '{0}'. Line breaks are not allowed.",
Expand Down
3 changes: 2 additions & 1 deletion Tasks/AzurePowerShell/Tests/DoesNotUnravelOutput.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ param()

# Arrange.
. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
Register-Mock Get-VstsInput { "$PSScriptRoot/DoesNotUnravelOutput_TargetScript.ps1" } -- -Name ScriptPath -Require
Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
Register-Mock Get-VstsInput { "$PSScriptRoot/DoesNotUnravelOutput_TargetScript.ps1" } -- -Name ScriptPath
Register-Mock Initialize-Azure

# Act.
Expand Down
3 changes: 3 additions & 0 deletions Tasks/AzurePowerShell/Tests/L0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ describe('AzurePowerShell Suite', function () {
it('performs basic flow', (done) => {
psr.run(path.join(__dirname, 'PerformsBasicFlow.ps1'), done);
})
it('validates inline script flow', (done) => {
psr.run(path.join(__dirname, 'ValidateInlineScriptFlow.ps1'), done);
})
it('redirects errors', (done) => {
psr.run(path.join(__dirname, 'RedirectsErrors.ps1'), done);
})
Expand Down
3 changes: 2 additions & 1 deletion Tasks/AzurePowerShell/Tests/PerformsBasicFlow.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ param()

# Arrange.
. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
Register-Mock Get-VstsInput { "$PSScriptRoot/PerformsBasicFlow_TargetScript.ps1" } -- -Name ScriptPath -Require
Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
Register-Mock Get-VstsInput { "$PSScriptRoot/PerformsBasicFlow_TargetScript.ps1" } -- -Name ScriptPath
Register-Mock Get-VstsInput { 'arg1 arg2' } -- -Name ScriptArguments
Register-Mock Initialize-Azure

Expand Down
3 changes: 2 additions & 1 deletion Tasks/AzurePowerShell/Tests/RedirectsErrors.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ param()

# Arrange.
. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
Register-Mock Get-VstsInput { "$PSScriptRoot/RedirectsErrors_TargetScript.ps1" } -- -Name ScriptPath -Require
Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
Register-Mock Get-VstsInput { "$PSScriptRoot/RedirectsErrors_TargetScript.ps1" } -- -Name ScriptPath
Register-Mock Initialize-Azure

# Act.
Expand Down
3 changes: 2 additions & 1 deletion Tasks/AzurePowerShell/Tests/RemovesFunctionsAndVariables.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ param()
. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1

# Arrange the task inputs.
Register-Mock Get-VstsInput { "$PSScriptRoot/RemovesFunctionsAndVariables_TargetScript.ps1" } -- -Name ScriptPath -Require
Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
Register-Mock Get-VstsInput { "$PSScriptRoot/RemovesFunctionsAndVariables_TargetScript.ps1" } -- -Name ScriptPath

# Arrange the mock task SDK module.
New-Module -Name VstsTaskSdk -ScriptBlock {
Expand Down
3 changes: 2 additions & 1 deletion Tasks/AzurePowerShell/Tests/ThrowsWhenInvalidScriptPath.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ param()
. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
foreach ($path in @( "script`rpath", "script`npath" )) {
Unregister-Mock Get-VstsInput
Register-Mock Get-VstsInput { $path } -- -Name ScriptPath -Require
Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
Register-Mock Get-VstsInput { $path } -- -Name ScriptPath

# Act/Assert.
Assert-Throws {
Expand Down
21 changes: 21 additions & 0 deletions Tasks/AzurePowerShell/Tests/ValidateInlineScriptFlow.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[CmdletBinding()]
param()

# Arrange.
. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
Unregister-Mock Get-VstsInput
Register-Mock Get-VstsInput { "InlineScript" } -- -Name ScriptType -Require
Register-Mock Get-VstsInput { ",@( 'item 1', 'item 2')" } -- -Name AzurePowerShellInline
Register-Mock Initialize-Azure

# Act.
$actual = @( & $PSScriptRoot\..\AzurePowerShell.ps1 )
$global:ErrorActionPreference = 'Stop' # Reset to stop.

# Assert the correct number of elements is returned.
Assert-AreEqual 1 $actual.Length

# Assert item 1 and 2 are in an array together.
Assert-AreEqual 2 @($actual[0]).Length
Assert-AreEqual 'item 1' $actual[0][0]
Assert-AreEqual 'item 2' $actual[0][1]
35 changes: 31 additions & 4 deletions Tasks/AzurePowerShell/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 1,
"Minor": 1,
"Patch": 3
"Patch": 4
},
"demands": [
"azureps"
Expand Down Expand Up @@ -54,13 +54,40 @@
"helpMarkDown": "Azure Resource Manager subscription to configure before running PowerShell",
"visibleRule": "ConnectedServiceNameSelector = ConnectedServiceNameARM"
},
{
"name": "ScriptType",
"type": "pickList",
"label": "Script Type",
"required": true,
"helpMarkDown": "Type of the script: File Path or Inline Script",
"defaultValue": "FilePath",
"options": {
"FilePath": "AzurePowerShell Script File Path",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, "AzurePowerShell" in the dropdown items seems redundant to me. it's the Azure PowerShell task, so this is implied already.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...nit continued :)

also, i would even say having "AzurePowerShell" in the dropdown item text may be confusing. the task initializes the Azure module and then runs the PowerShell script. other than the name of the task, there is no such thing as "Azure PowerShell"

"InlineScript": "Inline AzurePowerShell Script"
}
},
{
"name": "ScriptPath",
"type": "filePath",
"label": "Script Path",
"defaultValue": "",
"required": true,
"helpMarkDown": "Path of the script. Should be fully qualified path or relative to the default working directory."
"required": false,
"helpMarkDown": "Path of the script. Should be fully qualified path or relative to the default working directory.",
"visibleRule": "ScriptType = FilePath"
},
{
"name": "AzurePowerShellInline",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, "AzurePowerShell" in the input name seems redunant. it's the Azure PowerShell task.

"type": "multiLine",
"label": "Inline AzurePowerShell Script",
"required": false,
"defaultValue": "# You can write your azure powershell scripts inline here. \n# You can also pass predefined and custom variables to this script using arguments",
"helpMarkDown": "Enter the AzurePowerShell script to execute.",
"visibleRule": "ScriptType = InlineScript",
"properties": {
"resizable": "true",
"rows": "10",
"maxLength": "500"
}
},
{
"name": "ScriptArguments",
Expand All @@ -74,7 +101,7 @@
"helpMarkDown": "Additional parameters to pass to PowerShell. Can be either ordinal or named parameters."
}
],
"instanceNameFormat": "Azure PowerShell script: $(ScriptPath)",
"instanceNameFormat": "Azure PowerShell script: $(ScriptType)",
"execution": {
"PowerShell3": {
"target": "AzurePowerShell.ps1"
Expand Down
33 changes: 30 additions & 3 deletions Tasks/AzurePowerShell/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 1,
"Minor": 1,
"Patch": 3
"Patch": 4
},
"demands": [
"azureps"
Expand Down Expand Up @@ -54,13 +54,40 @@
"helpMarkDown": "ms-resource:loc.input.help.ConnectedServiceNameARM",
"visibleRule": "ConnectedServiceNameSelector = ConnectedServiceNameARM"
},
{
"name": "ScriptType",
"type": "pickList",
"label": "ms-resource:loc.input.label.ScriptType",
"required": true,
"helpMarkDown": "ms-resource:loc.input.help.ScriptType",
"defaultValue": "FilePath",
"options": {
"FilePath": "AzurePowerShell Script File Path",
"InlineScript": "Inline AzurePowerShell Script"
}
},
{
"name": "ScriptPath",
"type": "filePath",
"label": "ms-resource:loc.input.label.ScriptPath",
"defaultValue": "",
"required": true,
"helpMarkDown": "ms-resource:loc.input.help.ScriptPath"
"required": false,
"helpMarkDown": "ms-resource:loc.input.help.ScriptPath",
"visibleRule": "ScriptType = FilePath"
},
{
"name": "AzurePowerShellInline",
"type": "multiLine",
"label": "ms-resource:loc.input.label.AzurePowerShellInline",
"required": false,
"defaultValue": "# You can write your azure powershell scripts inline here. \n# You can also pass predefined and custom variables to this script using arguments",
"helpMarkDown": "ms-resource:loc.input.help.AzurePowerShellInline",
"visibleRule": "ScriptType = InlineScript",
"properties": {
"resizable": "true",
"rows": "10",
"maxLength": "500"
}
},
{
"name": "ScriptArguments",
Expand Down