chocolatey / boxstarter

Repeatable, reboot resilient windows environment installations made easy using Chocolatey packages
https://boxstarter.org/
Apache License 2.0
1.3k stars 162 forks source link

Chocolatey package fails when running Boxstarter with Packer #121

Closed JorritSalverda closed 5 years ago

JorritSalverda commented 8 years ago

When running the following provisioner with packer the installation of chocolatey package VisualStudio2013ExpressWeb and git.install fails (while other chocolatey packages run without issues).

The provisioner does the following:

{
      "type": "powershell",
      "inline": [
        "$ErrorActionPreference = \"Stop\"",
        "$env:chocolateyVersion = \"0.9.8.33\"",
        "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))",
        "cinst boxstarter -y",
        "& \"${env:AppData}\\Boxstarter\\BoxstarterShell.ps1\"",
        "$result = Install-BoxstarterPackage -PackageName c:\\Packerfile.ps1 -DisableReboots",
        "$result",
        "if ($result.Errors.Length -gt 0) { exit 1 }",
        "c:\\sysprep.ps1"
      ]
}

And Packerfile.ps1 has the following content:

cinst VisualStudio2013ExpressWeb
cinst git.install

It fails with an Unable to run scheduled task :

++ Boxstarter starting Calling Boxstarter's vendored Chocolatey to install VisualStudio2013ExpressWeb. This may take several minutes to complete...

Chocolatey (v0.9.8.33) is installing 'VisualStudio2013ExpressWeb' and dependencies. By installing you accept the license for 'VisualStudio2013ExpressWeb' and each dependency you are installing.
DotNet4.5.1 v4.5.1.20140606
Microsoft .Net 4.5.1 Framework is already installed on your machine.
VisualStudio2013ExpressWeb v12.0.21005.20150920

Downloading VisualStudio2013ExpressWeb 32 bit from 'http://download.microsoft.com/download/B/B/2/BB2AB17F-7BF1-477B-8BD5-488C843F122B/vns_full.exe'
Finished installing 'VisualStudio2013ExpressWeb' and dependencies - if errors not shown in console, none detected. Check log for errors if unsure.
++ Boxstarter finished Calling Boxstarter's vendored Chocolatey to install VisualStudio2013ExpressWeb. This may take several minutes to complete... 00:00:16.9417204
ERROR: The system cannot find the file specified.
Write-Error : VisualStudio2013ExpressWeb did not finish successfully. Boo to the chocolatey gods!
-----------------------
[ERROR] Unable to run scheduled task. Message from task was
-----------------------
At C:\Users\packeradmin\AppData\Roaming\Boxstarter\Chocolatey\chocolateyinstall\helpers\functions\Write-ChocolateyFailure.ps1:30 char:3
+   Write-Error $errorMessage
behaviors that change state without prompting for confirmation. Start
+   ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorExcep
using it now in your automated scripts.
tion
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExceptio
n,Write-Error

Write-Error : Package 'VisualStudio2013ExpressWeb v12.0.21005.20150920' did not install successfully: Unable to run scheduled task. Message from task was

When running the same cinst commands directly from packer without using boxstarter it installs fine.

Isn't the interception of chocolatey commands just for checking whether reboots are necessary? And wouldn't the DisableReboots option render this intercept unnecessary? I can't find anything about the intercept trying to wrap it in a scheduled task.

mwrock commented 8 years ago

Oh interesting. Boxstarter has some "special" logic it uses when running inside of a winrm session. It runs the MSIEXEC via a scheduled task. Boxstarter makes an incorrect assumption that only calls to Install-BoxstarterPackage using -ComputerName, -Session, or -ConnectionURI will be remote and it creates the scheduled task when that condition applies.

Here that assumption is broken because packer "owns" the winrm connection and not boxstarter.

I believe (and will double check) that this is addressed in the next version of boxstarter in progress. You can work around this for now by explicitly creating the Scheduled task first:

$secpasswd = ConvertTo-SecureString "vagrant" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ("vagrant", $secpasswd)
Create-BoxstarterTask $Credential
$result = Install-BoxstarterPackage -PackageName c:\\Packerfile.ps1 -DisableReboots
Remove-BoxstarterTask
JorritSalverda commented 8 years ago

Thanks! Unfortunately it results in The term 'Create-BoxstarterTask' is not recognized as the name of a cmdlet, even though I execute & "${env:AppData}\Boxstarter\BoxstarterShell.ps1 a couple of lines earlier. This should import the Boxstarter.Common module, right? Any thoughts?

mwrock commented 8 years ago

Ah I missed one detail. The Boxstarter.Common module is intended to be internal to boxstarter and its functions are not exposed outwards by default. However if you explicitly import it it should do the trick:

Import-Module "$($Boxstarter.BaseDir)\Boxstarter.Common\boxstarter.common.psd1
JorritSalverda commented 8 years ago

Thanks a lot, Matt, I got it working now! And it enables me to use Invoke-FromTask now as well.

Hopefully the next version does away with some of this boilerplate, so the provisioning part becomes a bit more concise. I've put my whole template below, it might help someone get this up and running.

The ticket can be closed, but maybe you need it open to verify this is fixed in the next version? Otherwise feel free to close it.

{
  "variables":
  {
    "gce_account_key_file": "{{env `GCE_ACCOUNT_KEY_FILE`}}",
    "gce_project_id": "{{env `GCE_PROJECT_ID`}}",
    "gce_zone": "{{env `GCE_ZONE`}}",
    "gce_network": "{{env `GCE_NETWORK`}}",
    "gce_use_internal_ip": "{{env `GCE_USE_INTERNAL_IP`}}",
    "gce_source_image": "{{env `GCE_SOURCE_IMAGE`}}",
    "gce_target_image": "{{env `GCE_TARGET_IMAGE`}}-{{env `GO_PIPELINE_LABEL`}}",
    "winrm_username": "{{env `WINRM_USERNAME`}}",
    "winrm_password": "{{env `WINRM_PASSWORD`}}",
    "winrm_timeout": "{{env `WINRM_TIMEOUT`}}",
    "startup_script": "winrm quickconfig -quiet & net user /add {{env `WINRM_USERNAME`}} {{env `WINRM_PASSWORD`}} & net localgroup administrators {{env `WINRM_USERNAME`}} /add & netsh advfirewall firewall set rule name=\"Windows Remote Management (HTTP-In)\" profile=public new remoteip=any & winrm set winrm/config/service @{AllowUnencrypted=\"true\"} & winrm set winrm/config/service/auth @{Basic=\"true\"} & powershell.exe -NoProfile -ExecutionPolicy Bypass -Command \"Set-ExecutionPolicy -ExecutionPolicy bypass -Force\""
  },
  "builders":
  [
    {
      "type": "googlecompute",
      "account_file": "{{user `gce_account_key_file`}}",
      "project_id": "{{user `gce_project_id`}}",
      "zone": "{{user `gce_zone`}}",
      "source_image": "{{user `gce_source_image`}}",
      "machine_type": "n1-standard-2",
      "disk_size": "50",
      "image_name": "{{user `gce_target_image`}}",
      "network": "{{user `gce_network`}}",
      "use_internal_ip": "{{user `gce_use_internal_ip`}}",
      "communicator": "winrm",
      "winrm_username": "{{user `winrm_username`}}",
      "winrm_password": "{{user `winrm_password`}}",
      "winrm_timeout": "{{user `winrm_timeout`}}",
      "metadata": { "windows-startup-script-cmd": "{{user `startup_script`}}" },
      "tags": ["allow-winrm-by-tag"]
    }
  ],
  "provisioners":
  [
    {
      "type": "file",
      "source": "./sysprep.ps1",
      "destination": "c:/sysprep.ps1"
    },
    {
      "type": "file",
      "source": "./entrypoint.ps1",
      "destination": "c:/entrypoint.ps1"
    },
    {
      "type": "file",
      "source": "./Packerfile.ps1",
      "destination": "c:/Packerfile.ps1"
    },
    {
      "type": "powershell",
      "inline": [
        "$ErrorActionPreference = \"Stop\"",
        "$env:chocolateyVersion = \"0.9.8.33\"",
        "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))",
        "cinst boxstarter -y",
        "& \"${env:AppData}\\Boxstarter\\BoxstarterShell.ps1\"",
        "Import-Module \"$($Boxstarter.BaseDir)\\Boxstarter.Common\\boxstarter.common.psd1\"",
        "$secpasswd = ConvertTo-SecureString \"{{user `winrm_password`}}\" -AsPlainText -Force",
        "$credential = New-Object System.Management.Automation.PSCredential (\"{{user `winrm_username`}}\", $secpasswd)",
        "Create-BoxstarterTask $credential",
        "$result = Install-BoxstarterPackage -PackageName c:\\Packerfile.ps1 -DisableReboots",
        "Remove-BoxstarterTask",
        "$result",
        "if ($result.Errors.Length -gt 0) { exit 1 }",
        "c:\\sysprep.ps1"
      ]
    }
  ]
}

Where sysprep.ps1 does the following


$ErrorActionPreference = "Stop"

trap
{
    Write-Error $_
    exit 1
}

Function CommandExists()
{
    param 
    (
        $command
    )

    $oldPreference = $ErrorActionPreference

    $ErrorActionPreference = 'stop'

    try 
    {
        if(Get-Command $command)
        {
            return $true
        }
    }
    catch 
    {
        return $false
    }
    finally 
    {
        $ErrorActionPreference=$oldPreference
    }
}

# cleanup and sysprep
if ((CommandExists GCESysprep) -eq $true)
{
    # google cloud
    Write-Output "Executing GCESysprep..."
    GCESysprep 
}
elseif (Test-Path "C:\Windows\Panther\unattend.xml")
{
    # aws
    Remove-Item c:\Windows\Temp\* -recurse -force

    & "c:\program files\Amazon\Ec2ConfigService\ec2config.exe" -sysprep
}

Packerfile.ps1 is my boxstarter script. entrypoint.ps1 is what I run to do some last config at runtime.

mwrock commented 8 years ago

Glad you got it working! I'll keep this open to make sure this gets fixed right.

michaelbarkdoll commented 8 years ago

Matt,

This issue also appears to affect chef on the client node when invoking Install-BoxstarterPackage inside a chef powershell_script over winrm that calls a boxstarter package. I was getting errors: https://gist.github.com/anonymous/e6a4f2c3abbab8bfd67b

I was finally able to get around these errors using: Import-Module Boxstarter.Chocolatey Import-Module "$($Boxstarter.BaseDir)\Boxstarter.Common\boxstarter.common.psd1" Create-BoxstarterTask $cred Install-BoxstarterPackage -PackageName deploywindows -LocalRepo C:\repo -Credential $cred Remove-BoxstarterTask

mwrock commented 8 years ago

Yeah. It would be impacted when called from any "provisioner-like" tool including chef, packer, vagrant, puppet, etc, etc. Plan to address this as soon as v2.6 is released (getting very close).

nevercast commented 6 years ago

I'm seeing what I believe to be this issue with Vagrant, WServer 2012R2 & Boxstarter. I'm using Boxstarter 2.10, is this issue expected to still be present?

pauby commented 5 years ago

@nevercast Can you see this message and the following one to see if this fixes your issue?

JorritSalverda commented 5 years ago

Not sure if this is still relevant. These days I create my windows vms with just packer version 1.3.5 (using the powershell provisioner), chocolatey 0.10.11 and without boxstarter; seems to work fine over winrm. So for me it's okay to close this issue unless you want to check whether it actually works with latest boxstarter.

pauby commented 5 years ago

Thanks @JorritSalverda