Uploaded image for project: 'Modules'
  1. Modules
  2. MODULES-8167

puppetlabs-chocolatey : installation errors only available in debug mode

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Ready for Engineering
    • Priority: Normal
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: chocolatey
    • Labels:
      None
    • Environment:
      • windows 10
      • puppetlabs-chocolatey 3.1.0
      • puppet agent 6.0.2
    • Template:
      MODULES Bug Template
    • Team:
      Windows
    • Sprint:
      Windows Hopper
    • Method Found:
      Needs Assessment
    • QA Risk Assessment:
      Needs Assessment

      Description

      Basic Info
      Module Version: 3.10
      Puppet Version: 6.0.0
      OS Name/Version: Windows 10

      When errors occur during chocolatey installation, error messages are swallowed unless running in debug mode. Normal agent runs will output the entire templated installation script twice with no indication of the error that occurred

      Desired Behavior:

      • Module should output the error encountered without needing debug mode
      • Script from templates/install_chocolatey.ps1.erb should not be echoed to screen

      Actual Behavior:
      In case of failure during chocolatey installation, user receives the message:

      Error: '# ==============================================================================
      # Copyright 2011 - Present RealDimensions Software, LLC
      #
      # Licensed under the Apache License, Version 2.0 (the "License"); you may not use
      # this file except in compliance with the License. You may obtain a copy of the
      # License at
      #
      #     http://www.apache.org/licenses/LICENSE-2.0
      #
      # Unless required by applicable law or agreed to in writing, software distributed
      # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
      # CONDITIONS OF ANY KIND, either express or implied. See the License for the
      # specific language governing permissions and limitations under the License.
      # ==============================================================================
       
      $ErrorActionPreference = 'Stop'
       
      # For some reason try/catch wrapping only ensures
      # that none of this script runs at all
      # https://tickets.puppetlabs.com/browse/MODULES-2634
      #try {
       
      # variables
      $url = 'http://packages.chocolatey.org/chocolatey.0.10.11.nupkgx'
      $unzipMethod = 'windows'
      if ($env:TEMP -eq $null) {
        $env:TEMP = Join-Path $env:SystemDrive 'temp'
      }
      $chocTempDir = Join-Path $env:TEMP "chocolatey"
      $tempDir = Join-Path $chocTempDir "chocInstall"
      if (![System.IO.Directory]::Exists($tempDir)) {[System.IO.Directory]::CreateDirectory($tempDir)}
      $file = Join-Path $tempDir "chocolatey.zip"
      $chocErrorLog = Join-Path $tempDir "chocError.log"
       
      # PowerShell v2/3 caches the output stream. Then it throws errors due
      # to the FileStream not being what is expected. Fixes "The OS handle's
      # position is not what FileStream expected. Do not use a handle
      # simultaneously in one FileStream and in Win32 code or another
      # FileStream."
       
      # This only works with the ConsoleHost (PowerShell InternalHost)
      function Fix-PowerShellOutputRedirectionBug {
        try{
          # http://www.leeholmes.com/blog/2008/07/30/workaround-the-os-handles-position-is-not-what-filestream-expected/ plus comments
          $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetField"
          $objectRef = $host.GetType().GetField("externalHostRef", $bindingFlags).GetValue($host)
          $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetProperty"
          $consoleHost = $objectRef.GetType().GetProperty("Value", $bindingFlags).GetValue($objectRef, @())
          [void] $consoleHost.GetType().GetProperty("IsStandardOutputRedirected", $bindingFlags).GetValue($consoleHost, @())
          $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetField"
          $field = $consoleHost.GetType().GetField("standardOutputWriter", $bindingFlags)
          $field.SetValue($consoleHost, [Console]::Out)
          [void] $consoleHost.GetType().GetProperty("IsStandardErrorRedirected", $bindingFlags).GetValue($consoleHost, @())
          $field2 = $consoleHost.GetType().GetField("standardErrorWriter", $bindingFlags)
          $field2.SetValue($consoleHost, [Console]::Error)
        } catch {
          Write-Output "Unable to apply redirection fix. Error: $_"
        }
      }
       
      Fix-PowerShellOutputRedirectionBug
       
      # This should help when certain organizations have issues installing Chocolatey
      # Attempt to set highest encryption available for SecurityProtocol.
      # PowerShell will not set this by default (until maybe .NET 4.6.x). This
      # will typically produce a message for PowerShell v2 (just an info
      # message though)
      try {
        # Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48)
        # Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't
        # exist in .NET 4.0, even though they are addressable if .NET 4.5+ is
        # installed (.NET 4.5 is an in-place upgrade).
        [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48
      } catch {
        Write-Output "Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to do one or more of the following: (1) upgrade to .NET Framework 4.5 and PowerShell v3 and/or (2) specify internal Chocolatey package location (see https://forge.puppet.com/puppetlabs/chocolatey#manage-chocolatey-installation)."
      }
       
      function Download-File {
      param (
        [string]$url,
        [string]$file
       )
        Write-Output "Downloading $url to $file"
        $downloader = new-object System.Net.WebClient
        $downloader.Proxy.Credentials=[System.Net.CredentialCache]::DefaultNetworkCredentials;
        $downloader.DownloadFile($url, $file)
      }
       
      # download the package
      Download-File $url $file
       
      if ($unzipMethod -eq '7zip') {
        # download 7zip
        Write-Output "Download 7Zip commandline tool"
        $7zaExe = Join-Path $tempDir '7za.exe'
       
        Download-File 'https://chocolatey.org/7za.exe' "$7zaExe"
       
        # unzip the package
        Write-Output "Extracting $file to $tempDir..."
        Start-Process "$7zaExe" -ArgumentList "x -o`"$tempDir`" -y `"$file`"" -Wait -NoNewWindow
      } else {
        if ($PSVersionTable.PSVersion.Major -lt 5) {
          $shellApplication = new-object -com shell.application
          $zipPackage = $shellApplication.NameSpace($file)
          $destinationFolder = $shellApplication.NameSpace($tempDir)
          $destinationFolder.CopyHere($zipPackage.Items(),0x10)
        } else {
          Expand-Archive -Path "$file" -DestinationPath "$tempDir" -Force | Out-Null
        }
      }
       
      # call chocolatey install
      Write-Output "Installing chocolatey on this machine"
      $toolsFolder = Join-Path $tempDir "tools"
      $chocInstallPS1 = Join-Path $toolsFolder "chocolateyInstall.ps1"
       
      if ($PSVersionTable.PSVersion.Major -gt 2) {
        & $chocInstallPS1
      } else {
        $output = Invoke-Expression $chocInstallPS1
        $output
        Write-Output "Any errors that occured during install or upgrade are logged here: $chocoErrorLog"
        $error | out-file $chocErrorLog
      }
       
      Write-Output 'Ensuring chocolatey commands are on the path'
      $chocInstallVariableName = "ChocolateyInstall"
      $chocoPath = [Environment]::GetEnvironmentVariable($chocInstallVariableName, [System.EnvironmentVariableTarget]::User)
      if ($chocoPath -eq $null -or $chocoPath -eq '') {
        $chocoPath = 'C:\ProgramData\Chocolatey'
      }
       
      $chocoBinPath = Join-Path $chocoPath 'bin'
       
      if ($($env:Path).ToLower().Contains($($chocoBinPath).ToLower()) -eq $false) {
        $env:Path = [Environment]::GetEnvironmentVariable('Path',[System.EnvironmentVariableTarget]::Machine);
      }
       
      Write-Output 'Ensuring chocolatey.nupkg is in the lib folder'
      $chocoPkgDir = Join-Path $chocoPath 'lib\chocolatey'
      $nupkg = Join-Path $chocoPkgDir 'chocolatey.nupkg'
      if (![System.IO.Directory]::Exists($chocoPkgDir)) { [System.IO.Directory]::CreateDirectory($chocoPkgDir); }
      Copy-Item "$file" "$nupkg" -Force -ErrorAction SilentlyContinue
       
      #}
      #catch
      #{
      #  Write-Host "$($_.Exception.Message)"
      #  exit 1
      #}
      ' returned 1 instead of one of [0]
      Error: /Stage[main]/Chocolatey::Install/Exec[install_chocolatey_official]/returns: change from 'notrun' to ['0'] failed: '# ==============================================================================
      # Copyright 2011 - Present RealDimensions Software, LLC
      #
      # Licensed under the Apache License, Version 2.0 (the "License"); you may not use
      # this file except in compliance with the License. You may obtain a copy of the
      # License at
      #
      #     http://www.apache.org/licenses/LICENSE-2.0
      #
      # Unless required by applicable law or agreed to in writing, software distributed
      # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
      # CONDITIONS OF ANY KIND, either express or implied. See the License for the
      # specific language governing permissions and limitations under the License.
      # ==============================================================================
       
      $ErrorActionPreference = 'Stop'
       
      # For some reason try/catch wrapping only ensures
      # that none of this script runs at all
      # https://tickets.puppetlabs.com/browse/MODULES-2634
      #try {
       
      # variables
      $url = 'http://packages.chocolatey.org/chocolatey.0.10.11.nupkgx'
      $unzipMethod = 'windows'
      if ($env:TEMP -eq $null) {
        $env:TEMP = Join-Path $env:SystemDrive 'temp'
      }
      $chocTempDir = Join-Path $env:TEMP "chocolatey"
      $tempDir = Join-Path $chocTempDir "chocInstall"
      if (![System.IO.Directory]::Exists($tempDir)) {[System.IO.Directory]::CreateDirectory($tempDir)}
      $file = Join-Path $tempDir "chocolatey.zip"
      $chocErrorLog = Join-Path $tempDir "chocError.log"
       
      # PowerShell v2/3 caches the output stream. Then it throws errors due
      # to the FileStream not being what is expected. Fixes "The OS handle's
      # position is not what FileStream expected. Do not use a handle
      # simultaneously in one FileStream and in Win32 code or another
      # FileStream."
       
      # This only works with the ConsoleHost (PowerShell InternalHost)
      function Fix-PowerShellOutputRedirectionBug {
        try{
          # http://www.leeholmes.com/blog/2008/07/30/workaround-the-os-handles-position-is-not-what-filestream-expected/ plus comments
          $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetField"
          $objectRef = $host.GetType().GetField("externalHostRef", $bindingFlags).GetValue($host)
          $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetProperty"
          $consoleHost = $objectRef.GetType().GetProperty("Value", $bindingFlags).GetValue($objectRef, @())
          [void] $consoleHost.GetType().GetProperty("IsStandardOutputRedirected", $bindingFlags).GetValue($consoleHost, @())
          $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetField"
          $field = $consoleHost.GetType().GetField("standardOutputWriter", $bindingFlags)
          $field.SetValue($consoleHost, [Console]::Out)
          [void] $consoleHost.GetType().GetProperty("IsStandardErrorRedirected", $bindingFlags).GetValue($consoleHost, @())
          $field2 = $consoleHost.GetType().GetField("standardErrorWriter", $bindingFlags)
          $field2.SetValue($consoleHost, [Console]::Error)
        } catch {
          Write-Output "Unable to apply redirection fix. Error: $_"
        }
      }
       
      Fix-PowerShellOutputRedirectionBug
       
      # This should help when certain organizations have issues installing Chocolatey
      # Attempt to set highest encryption available for SecurityProtocol.
      # PowerShell will not set this by default (until maybe .NET 4.6.x). This
      # will typically produce a message for PowerShell v2 (just an info
      # message though)
      try {
        # Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48)
        # Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't
        # exist in .NET 4.0, even though they are addressable if .NET 4.5+ is
        # installed (.NET 4.5 is an in-place upgrade).
        [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48
      } catch {
        Write-Output "Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to do one or more of the following: (1) upgrade to .NET Framework 4.5 and PowerShell v3 and/or (2) specify internal Chocolatey package location (see https://forge.puppet.com/puppetlabs/chocolatey#manage-chocolatey-installation)."
      }
       
      function Download-File {
      param (
        [string]$url,
        [string]$file
       )
        Write-Output "Downloading $url to $file"
        $downloader = new-object System.Net.WebClient
        $downloader.Proxy.Credentials=[System.Net.CredentialCache]::DefaultNetworkCredentials;
        $downloader.DownloadFile($url, $file)
      }
       
      # download the package
      Download-File $url $file
       
      if ($unzipMethod -eq '7zip') {
        # download 7zip
        Write-Output "Download 7Zip commandline tool"
        $7zaExe = Join-Path $tempDir '7za.exe'
       
        Download-File 'https://chocolatey.org/7za.exe' "$7zaExe"
       
        # unzip the package
        Write-Output "Extracting $file to $tempDir..."
        Start-Process "$7zaExe" -ArgumentList "x -o`"$tempDir`" -y `"$file`"" -Wait -NoNewWindow
      } else {
        if ($PSVersionTable.PSVersion.Major -lt 5) {
          $shellApplication = new-object -com shell.application
          $zipPackage = $shellApplication.NameSpace($file)
          $destinationFolder = $shellApplication.NameSpace($tempDir)
          $destinationFolder.CopyHere($zipPackage.Items(),0x10)
        } else {
          Expand-Archive -Path "$file" -DestinationPath "$tempDir" -Force | Out-Null
        }
      }
       
      # call chocolatey install
      Write-Output "Installing chocolatey on this machine"
      $toolsFolder = Join-Path $tempDir "tools"
      $chocInstallPS1 = Join-Path $toolsFolder "chocolateyInstall.ps1"
       
      if ($PSVersionTable.PSVersion.Major -gt 2) {
        & $chocInstallPS1
      } else {
        $output = Invoke-Expression $chocInstallPS1
        $output
        Write-Output "Any errors that occured during install or upgrade are logged here: $chocoErrorLog"
        $error | out-file $chocErrorLog
      }
       
      Write-Output 'Ensuring chocolatey commands are on the path'
      $chocInstallVariableName = "ChocolateyInstall"
      $chocoPath = [Environment]::GetEnvironmentVariable($chocInstallVariableName, [System.EnvironmentVariableTarget]::User)
      if ($chocoPath -eq $null -or $chocoPath -eq '') {
        $chocoPath = 'C:\ProgramData\Chocolatey'
      }
       
      $chocoBinPath = Join-Path $chocoPath 'bin'
       
      if ($($env:Path).ToLower().Contains($($chocoBinPath).ToLower()) -eq $false) {
        $env:Path = [Environment]::GetEnvironmentVariable('Path',[System.EnvironmentVariableTarget]::Machine);
      }
       
      Write-Output 'Ensuring chocolatey.nupkg is in the lib folder'
      $chocoPkgDir = Join-Path $chocoPath 'lib\chocolatey'
      $nupkg = Join-Path $chocoPkgDir 'chocolatey.nupkg'
      if (![System.IO.Directory]::Exists($chocoPkgDir)) { [System.IO.Directory]::CreateDirectory($chocoPkgDir); }
      Copy-Item "$file" "$nupkg" -Force -ErrorAction SilentlyContinue
       
      #}
      #catch
      #{
      #  Write-Host "$($_.Exception.Message)"
      #  exit 1
      #}
      ' returned 1 instead of one of [0]
      

       
      The cause as reported by the script is not in the output, user must run puppet with --debug and will then see messages like:

      *Wrong URL*

      Debug: STDERR: The remote server returned an error: (403) Forbidden.
      

       
      Disconnected

      Debug: STDERR: The remote name could not be resolved: 'packages.chocolatey.org'
      

      The script will occasionally give the above error message (cause unknown) when chocolatey installation was successful. I was only able to reproduce this once.

      Workaround
      When the above message is encountered, user must run puppet with --debug to be able to diagnose root cause of error (if there was really an error...).

        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            geoff@declarativesystems.com Geoff Williams
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated:

                Zendesk Support