diff --git a/Jenkinsfile_k8s b/Jenkinsfile_k8s index e152d6009..86266971b 100644 --- a/Jenkinsfile_k8s +++ b/Jenkinsfile_k8s @@ -1,14 +1,24 @@ // The node to be used depends on the build type: this function executes the pipeline code block provided as "body" // into the correct node type based on the provided arguments def withPackerNode(String packer_template, String compute_type, String cpu_architecture, Closure body) { - // Build ARM64 CPU Docker images on a native machine (faster than using the local qemu) - if (cpu_architecture == 'amd64' && compute_type == 'docker') { - node('linux-amd64-docker') { + // Docker images need to run with a local Docker Engine + if (compute_type == 'docker') { + String agentLabel = compute_type + '-' + packer_template + if (packer_template ==~ /ubuntu.*/) { + agentLabel = 'linux-amd64-docker' + } + node(agentLabel) { // New agent workspace specified as scripted requires an explicit checkout (compared to declarative) checkout scm // New agent means new packer project to initialize (plugins) - packerInitPlugins() + // packerInitPlugins() + + // Authenticating to the GitHub API with an API token (auto-generated IAT, valid for 1 hour) provided to the environment variable PACKER_GITHUB_API_TOKEN + // to avoid hitting the rate limit. Ref. https://www.packer.io/docs/commands/init. + withCredentials([usernamePassword(credentialsId: 'github-app-infra',usernameVariable: 'UNUSED',passwordVariable: 'PACKER_GITHUB_API_TOKEN')]) { + powershell 'packer init .' + } return body.call() } @@ -18,15 +28,24 @@ def withPackerNode(String packer_template, String compute_type, String cpu_archi } } +def universalShell(String command) { + if (isUnix()) { + // To allow using ASDF shims + withEnv(["PATH+ASDF=/home/jenkins/.asdf/shims:/home/jenkins/.asdf/bin"]) { + sh command + } + } else { + powershell command + } +} + // Initialize the packer project by installing the plugins in $PACKER_HOME_DIR/ - ref. https://www.packer.io/docs/configure // This function must be called for each distinct agent but only one time (as plugins are OS and CPU specifics) def packerInitPlugins() { // Authenticating to the GitHub API with an API token (auto-generated IAT, valid for 1 hour) provided to the environment variable PACKER_GITHUB_API_TOKEN // to avoid hitting the rate limit. Ref. https://www.packer.io/docs/commands/init. withCredentials([usernamePassword(credentialsId: 'github-app-infra',usernameVariable: 'UNUSED',passwordVariable: 'PACKER_GITHUB_API_TOKEN')]) { - // Cleanup any remnant of packer plugins on this agent - sh 'rm -rf /home/jenkins/.config /home/jenkins/.packer*' - sh 'packer init ./' + universalShell 'packer init .' } } @@ -56,80 +75,79 @@ pipeline { options { timeout(time: 120, unit: 'MINUTES') } - environment { - // To allow using ASDF shims - PATH = "${env.PATH}:/home/jenkins/.asdf/shims:/home/jenkins/.asdf/bin" - } stages { - stage('Side Tasks') { - environment { - DRYRUN = "${env.BRANCH_IS_PRIMARY ? 'false' : 'true'}" - } - parallel { - stage('Packer Init') { - steps { - // Call the initializing function once for the default agent - script { - packerInitPlugins() - } - } - } - stage('GC on Azure') { - environment { - PACKER_AZURE = credentials('packer-azure-serviceprincipal') - } - steps { - catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { - sh 'az login --service-principal -u "$PACKER_AZURE_CLIENT_ID" -p "$PACKER_AZURE_CLIENT_SECRET" -t "$PACKER_AZURE_TENANT_ID"' - sh 'az account set -s "$PACKER_AZURE_SUBSCRIPTION_ID"' - sh './cleanup/azure_gallery_images.sh 1 dev' - sh './cleanup/azure_gallery_images.sh 7 staging' - sh './cleanup/azure.sh 1 dev' - sh './cleanup/azure.sh 1 staging' - sh './cleanup/azure.sh 1 prod' - } - } - } - stage('Updatecli') { - steps { - catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { - script { - // TODO: Implement https://github.com/jenkins-infra/pipeline-library/issues/518 to allow using the updatecli() library function - withCredentials([ - usernamePassword( - credentialsId: 'github-app-updatecli-on-jenkins-infra', - usernameVariable: 'USERNAME_VALUE', // Setting this variable is mandatory, even if of not used when the credentials is a githubApp one - passwordVariable: 'UPDATECLI_GITHUB_TOKEN' - ) - ]) { - sh 'updatecli version' - sh 'updatecli diff --values ./updatecli/values.yaml --config ./updatecli/updatecli.d' - if (env.BRANCH_IS_PRIMARY) { - sh 'updatecli apply --values ./updatecli/values.yaml --config ./updatecli/updatecli.d' - } - } - } - } - } - } - } - } + // stage('Side Tasks') { + // environment { + // DRYRUN = "${env.BRANCH_IS_PRIMARY ? 'false' : 'true'}" + // } + // parallel { + // stage('Packer Init') { + // steps { + // // Call the initializing function once for the default agent + // script { + // packerInitPlugins() + // } + // } + // } + // stage('GC on Azure') { + // environment { + // PACKER_AZURE = credentials('packer-azure-serviceprincipal') + // } + // steps { + // catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + // sh 'az login --service-principal -u "$PACKER_AZURE_CLIENT_ID" -p "$PACKER_AZURE_CLIENT_SECRET" -t "$PACKER_AZURE_TENANT_ID"' + // sh 'az account set -s "$PACKER_AZURE_SUBSCRIPTION_ID"' + // sh './cleanup/azure_gallery_images.sh 1 dev' + // sh './cleanup/azure_gallery_images.sh 7 staging' + // sh './cleanup/azure.sh 1 dev' + // sh './cleanup/azure.sh 1 staging' + // sh './cleanup/azure.sh 1 prod' + // } + // } + // } + // stage('Updatecli') { + // steps { + // catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + // script { + // // TODO: Implement https://github.com/jenkins-infra/pipeline-library/issues/518 to allow using the updatecli() library function + // withCredentials([ + // usernamePassword( + // credentialsId: 'github-app-updatecli-on-jenkins-infra', + // usernameVariable: 'USERNAME_VALUE', // Setting this variable is mandatory, even if of not used when the credentials is a githubApp one + // passwordVariable: 'UPDATECLI_GITHUB_TOKEN' + // ) + // ]) { + // sh 'updatecli version' + // sh 'updatecli diff --values ./updatecli/values.yaml --config ./updatecli/updatecli.d' + // if (env.BRANCH_IS_PRIMARY) { + // sh 'updatecli apply --values ./updatecli/values.yaml --config ./updatecli/updatecli.d' + // } + // } + // } + // } + // } + // } + // } + // } stage('Packer Images') { matrix { axes { axis { name 'cpu_architecture' - values 'amd64', 'arm64' + // values 'amd64', 'arm64' + values 'amd64' } axis { name 'agent_type' // make sure to port any addition to the list of agent types to the Build Docker Manifest stage if it's docker related - values 'ubuntu-22.04', 'windows-2019', 'windows-2022' + // values 'ubuntu-22.04', 'windows-2019', 'windows-2022' + values 'windows-2019', 'windows-2022' } axis { name 'compute_type' // "azure-arm" stands for "Azure Resource Manager", unrelated to arm64 CPU - values 'azure-arm', 'docker' + // values 'azure-arm', 'docker' + values 'docker' } } excludes { @@ -148,27 +166,6 @@ pipeline { values 'azure-arm' } } - // No build on Windows or Docker, not yet implemented - exclude { - axis { - name 'agent_type' - values 'windows-2019' - } - axis { - name 'compute_type' - values 'docker' - } - } - exclude { - axis { - name 'agent_type' - values 'windows-2022' - } - axis { - name 'compute_type' - values 'docker' - } - } } environment { // Defines the following environment variables: AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID @@ -203,14 +200,14 @@ pipeline { withPackerNode(pkr_var_agent_os_type + '-' + pkr_var_agent_os_version , pkr_var_image_type, pkr_var_architecture) { // Validate template (for all elements) - sh 'PACKER_LOG=1 packer validate ./' + powershell 'packer validate .' // Execute build only for this matrix cell's setup retry(count: 2, conditions: [kubernetesAgent(handleNonKubernetes: true), nonresumable()]) { - sh 'packer build -timestamp-ui -force -only="${PKR_VAR_image_type}.${PKR_VAR_agent_os_type}" ./' + powershell 'packer build -timestamp-ui -force -only="${PKR_VAR_image_type}.${PKR_VAR_agent_os_type}" .' // adding manually a cpu architecture tag to the docker image if (pkr_var_image_type == 'docker') { - sh 'docker tag "jenkinsciinfra/jenkins-agent-${PKR_VAR_agent_os_type}-${PKR_VAR_agent_os_version}:latest" "jenkinsciinfra/jenkins-agent-${PKR_VAR_agent_os_type}-${PKR_VAR_agent_os_version}:${PKR_VAR_architecture}"' + powershell 'docker tag "jenkinsciinfra/jenkins-agent-${PKR_VAR_agent_os_type}-${PKR_VAR_agent_os_version}:latest" "jenkinsciinfra/jenkins-agent-${PKR_VAR_agent_os_type}-${PKR_VAR_agent_os_version}:${PKR_VAR_architecture}"' } } // if docker and building a tag, push to dockerhub from inside the node @@ -219,7 +216,7 @@ pipeline { stage('Publish all tags for Docker image') { echo "Pushing jenkinsciinfra/jenkins-agent-${pkr_var_agent_os_type}:${pkr_var_tag_name} & jenkinsciinfra/jenkins-agent-${pkr_var_agent_os_type}:latest for ${pkr_var_architecture}" infra.withDockerPushCredentials { - sh 'docker push --all-tags jenkinsciinfra/jenkins-agent-${agent_type}' + powershell 'docker push --all-tags jenkinsciinfra/jenkins-agent-${agent_type}' } } } diff --git a/build-jenkins-agent-ubuntu.pkr.hcl b/build-jenkins-agent-ubuntu.pkr.hcl index f4a45b1da..a0f1d1ff9 100644 --- a/build-jenkins-agent-ubuntu.pkr.hcl +++ b/build-jenkins-agent-ubuntu.pkr.hcl @@ -1,6 +1,24 @@ build { source "docker.base" { name = "ubuntu" + + # Use official ubuntu image, with the tag set to the numeric version + image = "${var.agent_os_type}:${var.agent_os_version}" + + # To improve audit and garbage collecting, we provide "labels" to the image + changes = [ + "LABEL timestamp = ${local.now_unix_timestamp}", + "LABEL version = ${var.image_version}", + "LABEL scm_ref = ${var.scm_ref}", + "LABEL build_type = ${var.build_type}", + "ENV LANG=${var.locale}", + "ENV LANGUAGE=${element(split(".", var.locale), 0)}:${element(split("_", var.locale), 0)}", + "ENV LC_ALL=${var.locale}", + "ENV AGENT_WORKDIR=/home/jenkins/agent", + "WORKDIR /home/jenkins", + "ENTRYPOINT [\"/usr/local/bin/jenkins-agent\"]", + "USER jenkins", + ] } source "azure-arm.base" { @@ -54,9 +72,9 @@ build { } post-processor "docker-tag" { - only = ["docker.ubuntu"] + only = ["docker.ubuntu"] # TODO specify architecture in image name with local.image_name - repository = format("%s/jenkins-agent-%s-%s",var.docker_namespace, var.agent_os_type, var.agent_os_version) + repository = format("%s/jenkins-agent-%s-%s", var.docker_namespace, var.agent_os_type, var.agent_os_version) tags = [var.image_version, "latest"] } } diff --git a/build-jenkins-agent-windows.pkr.hcl b/build-jenkins-agent-windows.pkr.hcl index be305594f..da4f4ea15 100644 --- a/build-jenkins-agent-windows.pkr.hcl +++ b/build-jenkins-agent-windows.pkr.hcl @@ -1,4 +1,31 @@ build { + source "docker.base" { + name = "windows" + + windows_container = true + + # https://hub.docker.com/_/microsoft-windows-servercore + image = "mcr.microsoft.com/windows/servercore:ltsc${var.agent_os_version}" + + # To improve audit and garbage collecting, we provide "labels" to the image + changes = [ + "LABEL timestamp = ${local.now_unix_timestamp}", + "LABEL version = ${var.image_version}", + "LABEL scm_ref = ${var.scm_ref}", + "LABEL build_type = ${var.build_type}", + "ENV LANG=${var.locale}", + "ENV LANGUAGE=${element(split(".", var.locale), 0)}:${element(split("_", var.locale), 0)}", + "ENV LC_ALL=${var.locale}", + "USER jenkins", + # https://github.com/jenkinsci/docker-agent/blob/1dd17e715fbebc7986154d5f54a0553d970dbf8d/11/windows/windowsservercore-ltsc2019/Dockerfile#L64 + "ENV AGENT_WORKDIR=C:/Users/jenkins/agent", + # https://github.com/jenkinsci/docker-agent/blob/1dd17e715fbebc7986154d5f54a0553d970dbf8d/11/windows/windowsservercore-ltsc2019/Dockerfile#L84 + "WORKDIR C:/Users/jenkins", + # https://github.com/jenkinsci/docker-inbound-agent/blob/708e03d72337cb6bc7debc1931ccb5019f82ecf6/11/windows/windowsservercore-ltsc2019/Dockerfile#L41 + "ENTRYPOINT [\"powershell.exe\", \"-f\", \"C:/ProgramData/Jenkins/jenkins-agent.ps1\"]", + ] + } + source "azure-arm.base" { name = "windows" communicator = "winrm" @@ -12,20 +39,30 @@ build { winrm_insecure = true winrm_timeout = "20m" winrm_use_ssl = true - winrm_username = local.windows_winrm_user[var.image_type] + winrm_username = local.windows_winrm_user } ## Why repeating? https://github.com/rgl/packer-plugin-windows-update/issues/90#issuecomment-842569865 # Note that restarts are only done when required by windows updates - provisioner "windows-update" { pause_before = "1m" } - provisioner "windows-update" { pause_before = "1m" } - provisioner "windows-update" { pause_before = "1m" } + provisioner "windows-update" { + only = ["azure-arm.windows"] + pause_before = "1m" + } + provisioner "windows-update" { + only = ["azure-arm.windows"] + pause_before = "1m" + } + provisioner "windows-update" { + only = ["azure-arm.windows"] + pause_before = "1m" + } # Installing Docker requires a restart: this first call to the installation script will prepare requirements provisioner "powershell" { + only = ["azure-arm.windows"] pause_before = "1m" environment_vars = local.provisioning_env_vars - elevated_user = local.windows_winrm_user[var.image_type] + elevated_user = local.windows_winrm_user elevated_password = build.Password inline = [ "Invoke-WebRequest -UseBasicParsing 'https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1' -o install-docker-ce.ps1", @@ -34,13 +71,16 @@ build { } # Required for loading Windows Container Feature - provisioner "windows-restart" {} + provisioner "windows-restart" { + only = ["azure-arm.windows"] + } # Install Docker-CE with Container feature loaded provisioner "powershell" { + only = ["azure-arm.windows"] pause_before = "1m" environment_vars = local.provisioning_env_vars - elevated_user = local.windows_winrm_user[var.image_type] + elevated_user = local.windows_winrm_user elevated_password = build.Password inline = [ "Invoke-WebRequest -UseBasicParsing 'https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1' -o install-docker-ce.ps1", @@ -49,32 +89,50 @@ build { } provisioner "file" { - pause_before = "1m" - source = "./provisioning/addSSHPubKey.ps1" - destination = "C:/" + source = "./provisioning/addSSHPubKey.ps1" + destination = "C:/" } provisioner "powershell" { - pause_before = "1m" + only = ["azure-arm.windows"] environment_vars = local.provisioning_env_vars - elevated_user = local.windows_winrm_user[var.image_type] + elevated_user = local.windows_winrm_user elevated_password = build.Password script = "./provisioning/windows-provision.ps1" } - # Recommended (and sometimes required) before running deprovisioning (sysprep) + provisioner "powershell" { + only = ["docker.windows"] + environment_vars = local.provisioning_env_vars + + # No elevated user for Docker provisioning + script = "provisioning/windows-provision.ps1" + # As per https://www.packer.io/docs/provisioners/powershell#execution_policy, avoid wrapping to see the exit code + execution_policy = "none" + } + + # Recommended (and sometimes required) before running deprovisioning (sysprep or AWS scripts) # ref. https:#www.packer.io/docs/builders/azure/arm#windows provisioner "windows-restart" { - max_retries = 3 + only = ["azure-arm.windows"] + pause_before = "1m" + max_retries = 3 } + # This provisioner must be the last for Azure builds, after reboots provisioner "powershell" { only = ["azure-arm.windows"] - elevated_user = local.windows_winrm_user[var.image_type] + elevated_user = local.windows_winrm_user elevated_password = build.Password inline = [ "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit /mode:vm", "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10 } else { break } }" ] } + + post-processor "docker-tag" { + only = ["docker.windows"] + repository = "${var.docker_namespace}/${local.image_name}" + tags = [var.image_version, "latest"] + } } diff --git a/install-packer.sh b/install-packer.sh deleted file mode 100755 index 5a09cbec7..000000000 --- a/install-packer.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash -# install-packer: install packer for the current architecture, -# in the directory specified as 1st argument, in the version specified as 2nd argument - -packer_install_dir="${1:?First argument missing: directory where to install packer.}" -packer_version="${2:?Second argument missing: version of packer to install.}" - -set -eu -o pipefail - -packer_cmd="packer" -temp_dir="$(mktemp -d)" -mkdir -p "${packer_install_dir}" - -## check if packer exists or install it -echo "====================================" - -## Check for presence of requirements or fail fast -for cli in curl unzip -do - if ! command -v $cli >/dev/null 2>&1 - then - echo "ERROR: command line ${cli} required but not found. Exiting." - exit 1 - fi -done - -echo "= Installing Packer version ${packer_version} to ${packer_install_dir}" - -if ! command -v ${packer_cmd} >/dev/null 2>&1 -then - if test -x "${packer_install_dir}/${packer_cmd}" - then - packer_cmd="${packer_install_dir}/packer" - else - echo "Detecting CPU architecture..." - arch=$(uname -m) - if [[ $arch == x86_64* ]]; then - echo "X64 Architecture" - packer_download_url="https://releases.hashicorp.com/packer/${packer_version}/packer_${packer_version}_linux_amd64.zip" - elif [[ $arch == i*86 ]]; then - echo "X32 Architecture" - packer_download_url="https://releases.hashicorp.com/packer/${packer_version}/packer_${packer_version}_linux_386.zip" - elif [[ $arch == arm* ]]; then - echo "ARM Architecture 32b" - packer_download_url="https://releases.hashicorp.com/packer/${packer_version}/packer_${packer_version}_linux_arm.zip" - elif [[ $arch == aarch64 ]]; then - echo "ARM Architecture 64b" - packer_download_url="https://releases.hashicorp.com/packer/${packer_version}/packer_${packer_version}_linux_arm64.zip" - else - echo "ERROR: unknwon architecture (${arch}). Exiting." - exit 2 - fi - - zip_file="${temp_dir}/packer.zip" - curl -sSL -o "${zip_file}" "${packer_download_url}" - unzip "${zip_file}" -d "${packer_install_dir}" - packer_cmd="${packer_install_dir}/packer" - fi -fi - -echo "= Packer installed, running sanity check (command '${packer_cmd} version')..." -"${packer_cmd}" version -echo "====================================" - -exit 0 diff --git a/locals.pkr.hcl b/locals.pkr.hcl index e5ff4f781..4ad31206e 100644 --- a/locals.pkr.hcl +++ b/locals.pkr.hcl @@ -9,10 +9,7 @@ locals { "amd64" = "${local.agent_os_version_safe}-lts-gen2" "arm64" = "${local.agent_os_version_safe}-lts-arm64" } - windows_winrm_user = { - "azure-arm" = "packer" - "docker" = "packer" - } + windows_winrm_user = "packer" azure_vm_size = { "amd64" = "Standard_D4s_v3" # 4 CPU / 16 GB / Huge size required to avoid https:#docs.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-troubleshoot#sysprep-timing and avoid full disk (DS2v2 only have 14 Gb SSD for system) "arm64" = "Standard_D4ps_v5" # 4 CPU / 16 GB diff --git a/provisioning/addSSHPubKey.ps1 b/provisioning/addSSHPubKey.ps1 index 93b62cf98..b1742676c 100644 --- a/provisioning/addSSHPubKey.ps1 +++ b/provisioning/addSSHPubKey.ps1 @@ -42,8 +42,5 @@ Match User $args[1] echo "$partialSSHConfig" | Out-File -Encoding ASCII -Append 'C:\ProgramData\ssh\sshd_config' } -## Ensure OpenSSH is reloaded -Restart-Service sshd - Write-Output "Key $publicKey added!" Write-Host "Key $publicKey added!" diff --git a/provisioning/windows-provision.ps1 b/provisioning/windows-provision.ps1 index f34a434c0..833002725 100644 --- a/provisioning/windows-provision.ps1 +++ b/provisioning/windows-provision.ps1 @@ -67,13 +67,27 @@ Function AddToPathEnv($path) { # Install OpenSSH (from Windows Features) Write-Output "= Installing OpenSSH Server..." -Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 -Write-Output "= Setting up OpenSSH Server..." -Set-Service -Name sshd -StartupType 'Automatic' -Write-Output "= Starting OpenSSH Server..." -Start-Service sshd -Write-Output "= Adding OpenSSH to the Firewall..." -New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 | Out-Null +if ($env:CLOUD_TYPE = "docker") { + Write-Output "== Docker Container: Setting up only OpenSSH client" + # No Service Manager in Docker + Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 +} else { + Write-Output "== Virtual Machine: Setting up both OpenSSH client and server" + Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 + Set-Service -Name sshd -StartupType 'Automatic' + Write-Output "== Virtual Machine: Set up OpenSSH keys" + ## Add a set of pre-defined SSH keys to allow faster agent startups + $temp_authorized_keys_file = 'C:\custom_auth_keys' + DownloadFile "$env:OPENSSH_AUTHORIZED_KEYS_URL" "$temp_authorized_keys_file" + foreach($line in Get-Content "$temp_authorized_keys_file") { + C:\addSSHPubKey.ps1 "$line" + } + Remove-Item -Force "$temp_authorized_keys_file" + Write-Output "= Starting OpenSSH Server..." + Start-Service sshd + Write-Output "= Adding OpenSSH to the Firewall..." + New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 | Out-Null +} # Prepare Tools Installation $baseDir = 'C:\tools' @@ -424,41 +438,39 @@ if ((Get-Host | Select-Object Version).Version.Major -eq 5) { Invoke-Command {& "choco.exe" install powershell --yes --no-progress --limit-output --fail-on-error-output;} AddToPathEnv "C:\Windows\System32\WindowsPowerShell\v1.0\" } -Write-Output "= Windows Powershell & Powershell Core sanity checks:" -Invoke-Command {& "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -command "(Get-Host).Version"} -Invoke-Command {& "C:\Program Files\PowerShell\7\pwsh.exe" -command "(Get-Host).Version"} - -## Add a set of pre-defined SSH keys to allow faster agent startups -$temp_authorized_keys_file = 'C:\custom_auth_keys' -DownloadFile "$env:OPENSSH_AUTHORIZED_KEYS_URL" "$temp_authorized_keys_file" -foreach($line in Get-Content "$temp_authorized_keys_file") { - C:\addSSHPubKey.ps1 "$line" -} -Remove-Item -Force "$temp_authorized_keys_file" - -## Final information: print out status -Write-Host "== OS Version" -[System.Environment]::OSVersion.Version - -Write-Host "== Disks" -Get-WmiObject -Class Win32_logicaldisk -Filter "DriveType = '3'" | -Select-Object -Property DeviceID, DriveType, VolumeName, -@{L='FreeSpaceGB';E={"{0:N2}" -f ($_.FreeSpace /1GB)}}, -@{L="Capacity";E={"{0:N2}" -f ($_.Size/1GB)}} | Format-Table -Property DeviceID, VolumeName, FreeSpaceGB, Capacity - -Write-Host "== Patch(s) installed" -Get-HotFix | Format-Table -Property HotFixID, Description, InstalledOn - -Write-Host "== Sanity Check of installed tools" -Write-Host "- Path environment" -Write-Host (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path -Write-Host '- Sanity check for docker' -& docker -v ## Client only -foreach($k in $downloads.Keys) { - $download = $downloads[$k] - if($download.ContainsKey('sanityCheck')) { - Write-Host "- Sanity check for $k" - Invoke-Command $download['sanityCheck'] + +# Only run sanity checks on Windows VMs +if ($env:CLOUD_TYPE -ne "docker") { + Write-Output "= Windows Powershell & Powershell Core sanity checks:" + Invoke-Command {& "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -command "(Get-Host).Version"} + Invoke-Command {& "C:\Program Files\PowerShell\7\pwsh.exe" -command "(Get-Host).Version"} + + # Final information: print out status + Write-Host "== OS Version" + [System.Environment]::OSVersion.Version + + Write-Host "== Disks" + Get-WmiObject -Class Win32_logicaldisk -Filter "DriveType = '3'" | + Select-Object -Property DeviceID, DriveType, VolumeName, + @{L='FreeSpaceGB';E={"{0:N2}" -f ($_.FreeSpace /1GB)}}, + @{L="Capacity";E={"{0:N2}" -f ($_.Size/1GB)}} | Format-Table -Property DeviceID, VolumeName, FreeSpaceGB, Capacity + + Write-Host "== Patch(s) installed" + Get-HotFix | Format-Table -Property HotFixID, Description, InstalledOn + + Write-Host "== Sanity Check of installed tools" + Write-Host "- Path environment" + Write-Host (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path + Write-Host '- Sanity check for docker' + & docker -v ## Client only + foreach($k in $downloads.Keys) { + $download = $downloads[$k] + if($download.ContainsKey('sanityCheck')) { + Write-Host "- Sanity check for $k" + Invoke-Command $download['sanityCheck'] + } } + Write-Host "== End of Sanity Check" } -Write-Host "== End of Sanity Check" + +Write-Host "== End of provisioning" diff --git a/sources.pkr.hcl b/sources.pkr.hcl index 4c2ce2cd7..033f1e21d 100644 --- a/sources.pkr.hcl +++ b/sources.pkr.hcl @@ -17,9 +17,9 @@ source "azure-arm" "base" { # Where to export the image shared_image_gallery_destination { - subscription = var.azure_subscription_id - resource_group = local.azure_destination_resource_group - gallery_name = "${var.build_type}_packer_images" + subscription = var.azure_subscription_id + resource_group = local.azure_destination_resource_group + gallery_name = "${var.build_type}_packer_images" # Not unique name defined in https://github.com/jenkins-infra/azure/blob/bfe56cb4f843b0c8029413090c383f7ac38dde2a/locals.tf#L4-L41 image_name = "${local.image_name}" image_version = var.image_version @@ -36,25 +36,8 @@ source "azure-arm" "base" { } } -# This source defines all the common settings for any Azure image (whatever Operating System) +# This source defines all the common settings for any Docker image (whatever Operating System) source "docker" "base" { - image = "${var.agent_os_type}:${var.agent_os_version}" - # Persist image on local docker engine commit = true - - # To improve audit and garbage collecting, we provide "labels" to the image - changes = [ - "LABEL timestamp = ${local.now_unix_timestamp}", - "LABEL version = ${var.image_version}", - "LABEL scm_ref = ${var.scm_ref}", - "LABEL build_type = ${var.build_type}", - "ENV LANG=${var.locale}", - "ENV LANGUAGE=${element(split(".", var.locale), 0)}:${element(split("_", var.locale), 0)}", - "ENV LC_ALL=${var.locale}", - "ENV AGENT_WORKDIR=/home/jenkins/agent", - "WORKDIR /home/jenkins", - "ENTRYPOINT [\"/usr/local/bin/jenkins-agent\"]", - "USER jenkins", - ] }