@ -16,25 +16,11 @@
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
$ErrorActionPreference = " Stop "
# WANT_JSON
# POWERSHELL_COMMON
function Write-Log
{
param
(
[ parameter ( mandatory = $false ) ]
[ System.String ]
$message
)
$date = get-date -format 'yyyy-MM-dd hh:mm:ss.zz'
Write-Host " $date | $message "
Out-File -InputObject " $date $message " -FilePath $global:LoggingFile -Append
}
$params = Parse-Args $args ;
$result = New-Object PSObject ;
Set-Attr $result " changed " $false ;
@ -48,21 +34,22 @@ Else
Fail-Json $result " missing required argument: name "
}
if( ( $params . logPath ) . length -gt 0 )
If ( $params . force )
{
$global:LoggingFile = $params . logPath
$force = $params . force | ConvertTo-Bool
}
e lse
E lse
{
$global:LoggingFile = " c:\ansible-playbook.log "
$force = $false
}
If ( $params . force )
If ( $params . upgrade )
{
$ force = $params . forc e | ConvertTo-Bool
$ upgrade = $params . upgrad e | ConvertTo-Bool
}
Else
{
$ forc e = $false
$ upgrad e = $false
}
If ( $params . version )
@ -74,6 +61,15 @@ Else
$version = $null
}
If ( $params . source )
{
$source = $params . source . ToString ( ) . ToLower ( )
}
Else
{
$source = $null
}
If ( $params . showlog )
{
$showlog = $params . showlog | ConvertTo-Bool
@ -96,157 +92,230 @@ Else
$state = " present "
}
$ChocoAlreadyInstalled = get-command choco -ErrorAction 0
if ( $ChocoAlreadyInstalled -eq $null )
{
#We need to install chocolatey
$install_choco_result = iex ( ( new-object net . webclient ) . DownloadString ( " https://chocolatey.org/install.ps1 " ) )
$result . changed = $true
$executable = " C:\ProgramData\chocolatey\bin\choco.exe "
}
Else
Function Chocolatey-Install-Upgrade
{
$executable = " choco.exe "
}
[ CmdletBinding ( ) ]
If ( $params . source )
{
$source = $params . source . ToString ( ) . ToLower ( )
If ( ( $source -ne " chocolatey " ) -and ( $source -ne " webpi " ) -and ( $source -ne " windowsfeatures " ) -and ( $source -ne " ruby " ) -and ( ! $source . startsWith ( " http:// " , " CurrentCultureIgnoreCase " ) ) -and ( ! $source . startsWith ( " https:// " , " CurrentCultureIgnoreCase " ) ) )
param ( )
$ChocoAlreadyInstalled = get-command choco -ErrorAction 0
if ( $ChocoAlreadyInstalled -eq $null )
{
#We need to install chocolatey
iex ( ( new-object net . webclient ) . DownloadString ( " https://chocolatey.org/install.ps1 " ) )
$result . changed = $true
$script:executable = " C:\ProgramData\chocolatey\bin\choco.exe "
}
else
{
Fail-Json $result " source is $source - must be one of chocolatey, ruby, webpi, windowsfeatures or a custom source url. "
$script:executable = " choco.exe "
if ( ( choco - -version ) -lt '0.9.9' )
{
Choco-Upgrade chocolatey
}
}
}
Elseif ( ! $params . source )
Function Choco-IsInstalled
{
$source = " chocolatey "
[ CmdletBinding ( ) ]
param (
[ Parameter ( Mandatory = $true , Position = 1 ) ]
[ string ] $package
)
$cmd = " $executable list --local-only $package "
$results = invoke-expression $cmd
if ( $LastExitCode -ne 0 )
{
Set-Attr $result " choco_error_cmd " $cmd
Set-Attr $result " choco_error_log " " $results "
Throw " Error checking installation status for $package "
}
If ( " $results " -match " $package .* (\d+) packages installed. " )
{
return $matches [ 1 ] -gt 0
}
$false
}
if ( $source -eq " webpi " )
Function Choco-Upgrade
{
# check whether 'webpi' installation source is available; if it isn't, install it
$webpi_check_cmd = " $executable list webpicmd -localonly "
$webpi_check_result = invoke-expression $webpi_check_cmd
Set-Attr $result " chocolatey_bootstrap_webpi_check_cmd " $webpi_check_cmd
Set-Attr $result " chocolatey_bootstrap_webpi_check_log " $webpi_check_result
if (
(
( $webpi_check_result . GetType ( ) . Name -eq " String " ) -and
( $webpi_check_result -match " No packages found " )
) -or
( $webpi_check_result -contains " No packages found. " )
[ CmdletBinding ( ) ]
param (
[ Parameter ( Mandatory = $true , Position = 1 ) ]
[ string ] $package ,
[ Parameter ( Mandatory = $false , Position = 2 ) ]
[string ] $version ,
[ Parameter ( Mandatory = $false , Position = 3 ) ]
[ string ] $source ,
[Parameter ( Mandatory = $false , Position = 4 ) ]
[bool ] $force
)
if ( -not ( Choco-IsInstalled $package ) )
{
#lessmsi is a webpicmd dependency, but dependency resolution fails unless it's installed separately
$lessmsi_install_cmd = " $executable install lessmsi "
$lessmsi_install_result = invoke-expression $lessmsi_install_cmd
Set-Attr $result " chocolatey_bootstrap_lessmsi_install_cmd " $lessmsi_install_cmd
Set-Attr $result " chocolatey_bootstrap_lessmsi_install_log " $lessmsi_install_result
throw " $package is not installed, you cannot upgrade "
}
$webpi_install_cmd = " $executable install webpicmd "
$webpi_install_result = invoke-expression $webpi_install_cmd
Set-Attr $result " chocolatey_bootstrap_webpi_install_cmd " $webpi_install_cmd
Set-Attr $result " chocolatey_bootstrap_webpi_install_log " $webpi_install_result
$cmd = " $executable upgrade -dv -y $package "
if ( ( $webpi_install_result | select-string " already installed " ) . length -gt 0 )
{
#no change
}
elseif ( ( $webpi_install_result | select-string " webpicmd has finished successfully " ) . length -gt 0 )
if ( $version )
{
$cmd + = " -version $version "
}
if ( $source )
{
$cmd + = " -source $source "
}
if ( $force )
{
$cmd + = " -force "
}
$results = invoke-expression $cmd
if ( $LastExitCode -ne 0 )
{
Set-Attr $result " choco_error_cmd " $cmd
Set-Attr $result " choco_error_log " " $results "
Throw " Error installing $package "
}
if ( " $results " -match ' upgraded (\d+)/\d+ package\(s\)\. ' )
{
if ( $matches [ 1 ] -gt 0 )
{
$result . changed = $true
}
Else
{
Fail-Json $result " WebPI install error: $webpi_install_result "
}
}
}
$expression = $executable
if ( $state -eq " present " )
{
$expression + = " install $package "
}
Elseif ( $state -eq " absent " )
{
$expression + = " uninstall $package "
}
if ( $force )
Function Choco-Install
{
if ( $state -eq " present " )
[ CmdletBinding ( ) ]
param (
[ Parameter ( Mandatory = $true , Position = 1 ) ]
[ string ] $package ,
[ Parameter ( Mandatory = $false , Position = 2 ) ]
[ string ] $version ,
[ Parameter ( Mandatory = $false , Position = 3 ) ]
[ string ] $source ,
[ Parameter ( Mandatory = $false , Position = 4 ) ]
[ bool ] $force ,
[ Parameter ( Mandatory = $false , Position = 5 ) ]
[ bool ] $upgrade
)
if ( Choco-IsInstalled $package )
{
$expression + = " -force "
if ( $upgrade )
{
Choco-Upgrade -package $package -version $version -source $source -force $force
}
return
}
}
if ( $version )
{
$expression + = " -version $version "
}
if ( $source -eq " chocolatey " )
{
$expression + = " -source https://chocolatey.org/api/v2/ "
}
elseif ( ( $source -eq " windowsfeatures " ) -or ( $source -eq " webpi " ) -or ( $source -eq " ruby " ) )
{
$expression + = " -source $source "
}
elseif ( ( $source -ne $Null ) -and ( $source -ne " " ) )
{
$expression + = " -source $source "
}
Set-Attr $result " chocolatey command " $expression
$op_result = invoke-expression $expression
if ( $state -eq " present " )
{
if (
( ( $op_result | select-string " already installed " ) . length -gt 0 ) -or
# webpi has different text output, and that doesn't include the package name but instead the human-friendly name
( ( $op_result | select-string " No products to be installed " ) . length -gt 0 )
)
$cmd = " $executable install -dv -y $package "
if ( $version )
{
#no change
$cmd + = " -version $version "
}
elseif (
( ( $op_result | select-string " has finished successfully " ) . length -gt 0 ) -or
# webpi has different text output, and that doesn't include the package name but instead the human-friendly name
( ( $op_result | select-string " Install of Products: SUCCESS " ) . length -gt 0 ) -or
( ( $op_result | select-string " gem installed " ) . length -gt 0 ) -or
( ( $op_result | select-string " gems installed " ) . length -gt 0 )
)
if ( $source )
{
$result . changed = $true
$cmd + = " -source $source "
}
if ( $force )
{
$cmd + = " -force "
}
Else
$results = invoke-expression $cmd
if ( $LastExitCode -ne 0 )
{
Fail-Json $result " Install error: $op_result "
Set-Attr $result " choco_error_cmd " $cmd
Set-Attr $result " choco_error_log " " $results "
Throw " Error installing $package "
}
$result . changed = $true
}
Elseif ( $state -eq " absent " )
Function Choco-Uninstall
{
$op_result = invoke-expression " $executable uninstall $package "
# HACK: Misleading - 'Uninstalling from folder' appears in output even when package is not installed, hence order of checks this way
if (
( ( $op_result | select-string " not installed " ) . length -gt 0 ) -or
( ( $op_result | select-string " Cannot find path " ) . length -gt 0 )
[ CmdletBinding ( ) ]
param (
[ Parameter ( Mandatory = $true , Position = 1 ) ]
[ string ] $package ,
[ Parameter ( Mandatory = $false , Position = 2 ) ]
[ string ] $version ,
[ Parameter ( Mandatory = $false , Position = 3 ) ]
[ bool ] $force
)
if ( -not ( Choco-IsInstalled $package ) )
{
#no change
return
}
elseif ( ( $op_result | select-string " Uninstalling from folder " ) . length -gt 0 )
$cmd = " $executable uninstall -dv -y $package "
if ( $version )
{
$result . changed = $true
$ cmd + = " -version $version "
}
else
if ( $force )
{
$cmd + = " -force "
}
$results = invoke-expression $cmd
if ( $LastExitCode -ne 0 )
{
Fail-Json $result " Uninstall error: $op_result "
Set-Attr $result " choco_error_cmd " $cmd
Set-Attr $result " choco_error_log " " $results "
Throw " Error uninstalling $package "
}
$result . changed = $true
}
Try
{
Chocolatey-Install -Upgrade
if ( $showlog )
if ( $state -eq " present " )
{
Choco-Install -package $package -version $version -source $source `
-force $force -upgrade $upgrade
}
else
{
Choco-Uninstall -package $package -version $version -force $force
}
Exit-Json $result ;
}
Catch
{
Set-Attr $result " chocolatey_log " $op_result
Fail-Json $result $_ . Exception . Message
}
Set-Attr $result " chocolatey_success " " true "
Exit-Json $result ;