Skip to content

Commit

Permalink
fix: Add config for windows ami (philips-labs#1525)
Browse files Browse the repository at this point in the history
* Add config for windows ami
* Update packer build to validate windows
  • Loading branch information
maths22 authored Jan 5, 2022
1 parent 4ec44df commit 7907984
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 12 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/packer-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ jobs:
runs-on: ubuntu-latest
container:
image: hashicorp/packer:1.7.8
strategy:
matrix:
image: ["linux-amzn2", "windows-core-2019"]
defaults:
run:
working-directory: images/linux-amzn2
working-directory: images/${{ matrix.image }}
steps:
- name: "Checkout"
uses: actions/checkout@v2

- name: packer init
run: packer init .

- name: check terraform formatting
- name: check packer formatting
run: packer fmt -recursive -check=true .

- name: packer validate
Expand Down
12 changes: 11 additions & 1 deletion examples/prebuilt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ This module shows how to create GitHub action runners using a prebuilt AMI for t

## Usages

Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md).
Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md).

## Variables

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_ami_filter"></a> [ami\_filter](#input\_ami\_filter) | The amis to search. Use the default for the provided amazon linux image, `github-runner-windows-core-2019-*` for the provided widnows image | `string` | `github-runner-amzn2-x86_64-2021*` | no |
| <a name="input_github_app_key_base64"></a> [github\_app\_key\_base64](#input\_github\_app\_key\_base64) | The base64 encoded private key you downloaded from GitHub when creating the app | `string` | | yes |
| <a name="input_github_app_id"></a> [github\_app\_id](#input\_github\_app\_id) | The id of the app you created on GitHub | `string` | | yes |
| <a name="input_region"></a> [region](#input\_region) | The target aws region | `string` | `eu-west-1` | no |
| <a name="input_runner_os"></a> [runner\_os](#input\_runner\_os) | The os of the image, either `linux` or `windows` | `string` | `linux` | no |

### Lambdas

Expand Down
13 changes: 7 additions & 6 deletions examples/prebuilt/main.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
locals {
environment = "prebuilt"
aws_region = "eu-west-1"
}

resource "random_id" "random" {
Expand All @@ -12,7 +11,7 @@ data "aws_caller_identity" "current" {}
module "runners" {
source = "../../"
create_service_linked_role_spot = true
aws_region = local.aws_region
aws_region = var.aws_region
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets

Expand All @@ -24,15 +23,17 @@ module "runners" {
webhook_secret = random_id.random.hex
}

webhook_lambda_zip = "../../lambda_output/webhook.zip"
runner_binaries_syncer_lambda_zip = "../../lambda_output/runner-binaries-syncer.zip"
runners_lambda_zip = "../../lambda_output/runners.zip"
webhook_lambda_zip = "lambdas-download/webhook.zip"
runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip"
runners_lambda_zip = "lambdas-download/runners.zip"

runner_extra_labels = "default,example"

runner_os = var.runner_os

# configure your pre-built AMI
enabled_userdata = false
ami_filter = { name = ["github-runner-amzn2-x86_64-2021*"] }
ami_filter = { name = [var.ami_name_filter] }
ami_owners = [data.aws_caller_identity.current.account_id]

# enable access to the runners via SSM
Expand Down
2 changes: 1 addition & 1 deletion examples/prebuilt/providers.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
provider "aws" {
region = local.aws_region
region = var.aws_region
}
15 changes: 15 additions & 0 deletions examples/prebuilt/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,18 @@
variable "github_app_key_base64" {}

variable "github_app_id" {}

variable "runner_os" {
type = string
default = "linux"
}

variable "ami_name_filter" {
type = string
default = "github-runner-amzn2-x86_64-2021*"
}

variable "aws_region" {
type = string
default = "eu-west-1"
}
2 changes: 1 addition & 1 deletion examples/prebuilt/vpc.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ module "vpc" {
source = "git::https://github.com/philips-software/terraform-aws-vpc.git?ref=2.2.0"

environment = local.environment
aws_region = local.aws_region
aws_region = var.aws_region
create_private_hosted_zone = false
}
2 changes: 1 addition & 1 deletion images/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The images inside this folder are pre-built images designed to shorten the boot

These images share the same scripting as used in the user-data mechanism in `/modules/runners/templates/`. We use a `tempaltefile` mechanism to insert the relevant script fragments into the scripts used for provisioning the images.

The example in `linux-amzn2` also uploads a `start-runner.sh` script that uses the exact same startup process as used in the user-data mechanism. This means that the image created here does not need any extra scripts injected or changes to boot up and connect to GH.
The examples in `linux-amzn2` and `windows-core-2019` also upload a `start-runner` script that uses the exact same startup process as used in the user-data mechanism. This means that the image created here does not need any extra scripts injected or changes to boot up and connect to GH.

## Building your own

Expand Down
8 changes: 8 additions & 0 deletions images/install-runner.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash -e

user_name=ec2-user

## This wrapper file re-uses scripts in the /modules/runners/templates directory
## of this repo. These are the same that are used by the user_data functionality
## to bootstrap the instance if it is started from an existing AMI.
${install_runner}
3 changes: 3 additions & 0 deletions images/start-runner.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Start-Transcript -Path "C:\runner-startup.log" -Append
${start_runner}
Stop-Transcript
38 changes: 38 additions & 0 deletions images/windows-core-2019/bootstrap_win.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<powershell>

Write-Output "Running User Data Script"
Write-Host "(host) Running User Data Script"

Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore

# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"

# Remove HTTP listener
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse

# Create a self-signed certificate to let ssl work
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force

# WinRM
Write-Output "Setting up WinRM"
Write-Host "(host) setting up WinRM"

# I'm not really sure why we need the cmd.exe wrapper, but it works with it and doesn't work without it
cmd.exe /c winrm quickconfig -q
cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}"
cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986"
cmd.exe /c net stop winrm
cmd.exe /c sc config winrm start= auto
cmd.exe /c net start winrm

</powershell>
66 changes: 66 additions & 0 deletions images/windows-core-2019/github_agent.windows.pkr.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
packer {
required_plugins {
amazon = {
version = ">= 0.0.2"
source = "github.com/hashicorp/amazon"
}
}
}

variable "action_runner_url" {
description = "The URL to the tarball of the action runner"
type = string
default = "https://github.com/actions/runner/releases/download/v2.285.1/actions-runner-win-x64-2.285.1.zip"
}

variable "region" {
description = "The region to build the image in"
type = string
default = "eu-west-1"
}

source "amazon-ebs" "githubrunner" {
ami_name = "github-runner-windows-core-2019-${formatdate("YYYYMMDDhhmm", timestamp())}"
communicator = "winrm"
instance_type = "t3a.medium"
region = var.region
source_ami_filter {
filters = {
name = "Windows_Server-2019-English-Core-ContainersLatest-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["amazon"]
}
tags = {
OS_Version = "windows-core-2019"
Release = "Latest"
Base_AMI_Name = "{{ .SourceAMIName }}"
}
user_data_file = "./bootstrap_win.ps1"
winrm_insecure = true
winrm_port = 5986
winrm_use_ssl = true
winrm_username = "Administrator"
}

build {
name = "githubactions-runner"
sources = [
"source.amazon-ebs.githubrunner"
]

provisioner "file" {
content = templatefile("../start-runner.ps1", {
start_runner = templatefile("../../modules/runners/templates/start-runner.ps1", {})
})
destination = "C:\\start-runner.ps1"
}

provisioner "powershell" {
inline = [templatefile("./windows-provisioner.ps1", {
action_runner_url = var.action_runner_url
})]
}
}
52 changes: 52 additions & 0 deletions images/windows-core-2019/windows-provisioner.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
$ErrorActionPreference = "Continue"
$VerbosePreference = "Continue"

# Install Chocolatey
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
$env:chocolateyUseWindowsCompression = 'true'
Invoke-WebRequest https://chocolatey.org/install.ps1 -UseBasicParsing | Invoke-Expression

# Add Chocolatey to powershell profile
$ChocoProfileValue = @'
$ChocolateyProfile = "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
if (Test-Path($ChocolateyProfile)) {
Import-Module "$ChocolateyProfile"
}
refreshenv
'@
# Write it to the $profile location
Set-Content -Path "$PsHome\Microsoft.PowerShell_profile.ps1" -Value $ChocoProfileValue -Force
# Source it
. "$PsHome\Microsoft.PowerShell_profile.ps1"

refreshenv

Write-Host "Installing cloudwatch agent..."
Invoke-WebRequest -Uri https://s3.amazonaws.com/amazoncloudwatch-agent/windows/amd64/latest/amazon-cloudwatch-agent.msi -OutFile C:\amazon-cloudwatch-agent.msi
$cloudwatchParams = '/i', 'C:\amazon-cloudwatch-agent.msi', '/qn', '/L*v', 'C:\CloudwatchInstall.log'
Start-Process "msiexec.exe" $cloudwatchParams -Wait -NoNewWindow
Remove-Item C:\amazon-cloudwatch-agent.msi

# Install dependent tools
Write-Host "Installing additional development tools"
choco install git awscli -y
refreshenv

Write-Host "Creating actions-runner directory for the GH Action installtion"
New-Item -ItemType Directory -Path C:\actions-runner ; Set-Location C:\actions-runner

Write-Host "Downloading the GH Action runner from ${action_runner_url}"
Invoke-WebRequest -Uri ${action_runner_url} -OutFile actions-runner.zip

Write-Host "Un-zip action runner"
Expand-Archive -Path actions-runner.zip -DestinationPath .

Write-Host "Delete zip file"
Remove-Item actions-runner.zip

$action = New-ScheduledTaskAction -WorkingDirectory "C:\actions-runner" -Execute "PowerShell.exe" -Argument "-File C:\start-runner.ps1"
$trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -TaskName "runnerinit" -Action $action -Trigger $trigger -User System -RunLevel Highest -Force

C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule

0 comments on commit 7907984

Please sign in to comment.