AWS Developer Tools Blog

Using NuGet and Chocolatey package managers in AWS CloudFormation and AWS Elastic Beanstalk

In this guest post by AWS Solutions Architect Lee Atkinson, we are going to describe how you can take advantage of the NuGet and Chocolatey package managers inside your CloudFormation templates and Elastic Beanstalk applications.

AWS CloudFormation and AWS Elastic Beanstalk support the Microsoft Windows Installer for installing .msi files onto Microsoft Windows instances managed by those services. For details on how to do this for CloudFormation, see http://docs.thinkwithwp.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html#aws-resource-init-packages, and for Elastic Beanstalk, see http://docs.thinkwithwp.com/elasticbeanstalk/latest/dg/customize-containers-windows-ec2.html#customize-containers-windows-format-packages.

NuGet (pronounced ‘New Get’) is a package manager for installing .NET development packages onto your development machine. It is available as a Microsoft Windows Visual Studio plugin as well as a standalone command line tool. Users can install packages from, and publish packages to, a central repository for packages located at http://www.nuget.org/.

Chocolatey NuGet builds on top of NuGet to provide a package manager for Microsoft Windows applications and describes itself as "a Machine Package Manager, somewhat like apt-get, but built with Windows in mind." It has a command line tool and a central repository located at http://chocolatey.org/.

AWS CloudFormation supports the downloading of files and execution of commands on EC2 instance creation using an application called ‘cfn-init.exe’ installed on instances running Microsoft Windows. We can leverage this functionality to install and execute both NuGet and Chocolatey. For more information on bootstrapping Microsoft Windows instances in CloudFormation, see http://docs.thinkwithwp.com/AWSCloudFormation/latest/UserGuide/cfn-windows-stacks-bootstrapping.html.

Similarly, AWS Elastic Beanstalk supports the downloading of files and execution of commands on instance creation using container customization. We can use this functionality to install and execute both NuGet and Chocolatey. For more information on customizing Microsoft Windows containers in Elastic Beanstalk, see http://docs.thinkwithwp.com/elasticbeanstalk/latest/dg/customize-containers-windows-ec2.html.

Using NuGet in AWS CloudFormation

For installing NuGet packages on an EC2 instance using AWS CloudFormation, we can use the NuGet command line tool. First, we need to download the tool to the Microsoft Windows instance, and we can use the CloudFormation ‘file’ declaration. Then, to install NuGet packages, we can use a CloudFormation ‘command’ declaration.

Here’s an excerpt from an example AWS CloudFormation template to:

  1. Download NuGet.exe
  2. Install the JSON.NET NuGet package
  3. Install the Entity Framework NuGet package
"AWS::CloudFormation::Init": {
  "config": {
    "files" : {
      "c:/tools/nuget.exe" : {
        "source" : "https://nuget.org/nuget.exe"
      }
    },
    "commands" : {
      "1-create-myapp-folder" : {
        "command" : "if not exist c:\myapp mkdir c:\myapp",
        "waitAfterCompletion" : "0"
      },
      "2-install-json-net" : {
        "command" : "c:\tools\nuget install Newtonsoft.Json -NonInteractive -OutputDirectory c:\myapp",
        "waitAfterCompletion" : "0"
      },
      "3-install-entityframework" : {
        "command" : "c:\tools\nuget install EntityFramework -NonInteractive -OutputDirectory c:\myapp",
        "waitAfterCompletion" : "0"
      }
    }
  }
}

Using Chocolatey in AWS CloudFormation

Installing and using Chocolatey is similar to NuGet above, though the recommended way of installing Chocolatey is to execute a Microsoft Windows PowerShell script. As CloudFormation ‘command’ declarations are executed by cmd.exe, we need to execute PowerShell.exe and provide the install command to that.

The Chocolatey installer and the packages it installs may modify the machine’s PATH environment variable. This adds complexity since subsequent commands after these installations are executed in the same session, which does not have the updated PATH. To overcome this, we utilize a command file to set the session’s PATH to that of the machine before it executes our command.

Here’s an excerpt from an example AWS CloudFormation template to:

  1. Create a command file ‘ewmp.cmd’ to execute a command with the machine’s PATH
  2. Install Chocolatey
  3. Install Sublime Text 3
  4. Install Firefox
"AWS::CloudFormation::Init": {
  "config": {
    "files" : {
      "c:/tools/ewmp.cmd" : {
        "content": "@ECHO OFFnFOR /F "tokens=3,*" %%a IN ('REG QUERY "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v PATH') DO PATH %%a%%bn%*"
      }
    },
    "commands" : {
      "1-install-chocolatey" : {
        "command" : "powershell -NoProfile -ExecutionPolicy unrestricted -Command "Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))""
      },
      "2-install-sublimetext" : {
        "command" : "c:\tools\ewmp choco install sublimetext3"
      },
      "3-install-firefox" : {
        "command" : "c:\tools\ewmp choco install firefox"
      }
    }
  }
}

Using NuGet and Chocolatey together in AWS CloudFormation

Another example for NuGet is when you are cloning a repository from a version control system that does not have the NuGet packages checked-in, which means those packages are missing from the clone. In this case, you can perform a NuGet Restore, which instructs NuGet to download the packages specified within the repository.

But we need to install git before we can clone—so we use Chocolatey!

Here’s an excerpt from an example AWS CloudFormation template to:

  1. Download NuGet.exe
  2. Create a command file ‘ewmp.cmd’ to execute a command with the machine’s PATH
  3. Install Chocolatey
  4. Install Git
  5. Clone a Git repository
  6. Restore NuGet packages defined in the repository’s solution file
"AWS::CloudFormation::Init": {
  "config": {
    "files" : {
      "c:/tools/nuget.exe" : {
        "source" : "https://nuget.org/nuget.exe"
      },
      "c:/tools/ewmp.cmd" : {
        "content": "@ECHO OFFnFOR /F "tokens=3,*" %%a IN ('REG QUERY "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v PATH') DO PATH %%a%%bn%*"
      }
    },
    "commands" : {
      "1-install-chocolatey" : {
        "command" : "powershell -NoProfile -ExecutionPolicy unrestricted -Command "Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"",
        "waitAfterCompletion" : "0"
      },
      "2-install-git" : {
        "command" : "c:\tools\ewmp choco install git",
        "waitAfterCompletion" : "0"
      },
      "3-create-myapp-folder" : {
        "command" : "if not exist c:\myapp mkdir c:\myapp",
        "waitAfterCompletion" : "0"
      },
      "4-clone-repo" : {
        "command" : "c:\tools\ewmp git clone git://github.com/aws/aws-sdk-net c:\myapp",
        "waitAfterCompletion" : "0"
      },
      "5-nuget-restore" : {
        "command" : "c:\tools\nuget restore c:\myapp\AWSSDK_DotNet.Mobile.sln",
        "waitAfterCompletion" : "0"
      }
    }
  }
}

Using NuGet and Chocolatey in AWS Elastic Beanstalk

The above examples can be translated into AWS Elastic Beanstalk config files to enable use of both NuGet and Chocolatey in Elastic Beanstalk. For Elastic Beanstalk, we create YAML .config files inside the .ebextensions folder of our source bundle.

Here’s an example .ebextensions config file to:

  1. Download NuGet.exe
  2. Install the JSON.NET NuGet package
  3. Install the Entity Framework NuGet package
files:
  c:/tools/nuget.exe:
    source: https://nuget.org/nuget.exe
commands:
  1-create-myapp-folder:
    command: if not exist c:myapp mkdir c:myapp
    waitAfterCompletion: 0
  2-install-json-net:
    command: c:toolsnuget install Newtonsoft.Json -NonInteractive -OutputDirectory c:myapp
    waitAfterCompletion: 0
  3-install-entityframework:
    command: c:toolsnuget install EntityFramework -NonInteractive -OutputDirectory c:myapp
    waitAfterCompletion: 0

Here’s an example .ebextensions config file to:

  1. Create a command file ‘ewmp.cmd’ to execute a command with the machine’s PATH
  2. Install Chocolatey
  3. Install Sublime Text 3
  4. Install Firefox
files:
  c:/tools/ewmp.cmd:
    content: |
      @ECHO OFF
      FOR /F "tokens=3,*" %%a IN ('REG QUERY "HKLMSystemCurrentControlSetControlSession ManagerEnvironment" /v PATH') DO PATH %%a%%b
      %*
commands:
  1-install-chocolatey:
    command: powershell -NoProfile -ExecutionPolicy unrestricted -Command "Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"
  2-install-sublimetext:
    command: c:toolsewmp choco install sublimetext3
  3-install-firefox:
    command: c:toolsewmp choco install firefox

Here’s an example .ebextensions config file to:

  1. Download NuGet.exe
  2. Create a command file ‘ewmp.cmd’ to execute a command with the machine’s PATH
  3. Install Chocolatey
  4. Install Git
  5. Clone a Git repository
  6. Restore NuGet packages defined in the repository’s solution file
files:
  c:/tools/nuget.exe:
    source: https://nuget.org/nuget.exe
  c:/tools/ewmp.cmd:
    content: |
      @ECHO OFF
      FOR /F "tokens=3,*" %%a IN ('REG QUERY "HKLMSystemCurrentControlSetControlSession ManagerEnvironment" /v PATH') DO PATH %%a%%b
      %*
commands:
  1-install-chocolatey:
    command: powershell -NoProfile -ExecutionPolicy unrestricted -Command "Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"
    waitAfterCompletion: 0
  2-install-git:
    command: c:toolsewmp choco install git
    waitAfterCompletion: 0
  3-create-myapp-folder:
    command: if not exist c:myapp mkdir c:myapp
    waitAfterCompletion: 0
  4-clone-repo:
    command: c:toolsewmp git clone git://github.com/aws/aws-sdk-net c:myapp
    waitAfterCompletion: 0
  5-nuget-restore:
    command: c:toolsnuget restore c:myappAWSSDK_DotNet.Mobile.sln
    waitAfterCompletion: 0

Summary

I hope this provides inspiration on how you can leverage both NuGet and Chocolatey to configure your Microsoft Windows instances managed by either AWS CloudFormation or AWS Elastic Beanstalk.