Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .buildkite/pipeline.elastic-agent-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,25 @@ steps:
- false
- true

- label: ":package: :windows: Package Windows Docker Container"
key: package_elastic-agent-windows-docker
depends_on: package_elastic-agent
agents:
provider: "gcp"
image: "family/elastic-workers-windows-2022"
machineType: "n2-standard-8"
diskSizeGb: 200
env:
PLATFORMS: "windows/amd64"
PACKAGES: "docker"
command: |
powershell -ExecutionPolicy Bypass -File .buildkite/scripts/steps/package-windows-docker.ps1
artifact_paths:
- "build/distributions/**/*"
plugins:
- elastic/vault-docker-login#v0.5.2:
secret_path: 'kv/ci-shared/platform-ingest/elastic_docker_registry'

- label: ":elastic-stack: Publishing to DRA"
if: build.env("BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG") == null || build.env("BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG") != "independent-agent-release-staging"
key: dra-publish
Expand Down
60 changes: 60 additions & 0 deletions .buildkite/scripts/steps/package-windows-docker.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# PowerShell script for packaging Windows Docker containers in Buildkite
# This script runs on a Windows agent with Docker Desktop in Windows container mode

$ErrorActionPreference = "Stop"

Write-Host "--- Setting up environment"

# Check if MANIFEST_URL is set
if (-not $env:MANIFEST_URL) {
$env:MANIFEST_URL = & buildkite-agent meta-data get MANIFEST_URL --default ""
if (-not $env:MANIFEST_URL) {
Write-Host "ERROR: Missing MANIFEST_URL variable or empty string provided" -ForegroundColor Red
exit 1
}
}

# Set MAGEFILE_VERBOSE if not set
if (-not $env:MAGEFILE_VERBOSE) {
$env:MAGEFILE_VERBOSE = & buildkite-agent meta-data get MAGEFILE_VERBOSE --default "0"
}

# Create the agent drop path
$env:AGENT_DROP_PATH = "build/elastic-agent-drop"
New-Item -ItemType Directory -Force -Path $env:AGENT_DROP_PATH | Out-Null

Write-Host "+++ Downloading Windows binary artifact from previous step"
# Download the pre-built Windows binary from the Linux cross-build step
& buildkite-agent artifact download "build/golang-crossbuild/elastic-agent-windows-amd64.exe" .
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: Failed to download Windows binary artifact" -ForegroundColor Red
exit $LASTEXITCODE
}

Write-Host "+++ Verifying Docker is in Windows container mode"
$dockerInfo = & docker info 2>&1
if ($dockerInfo -match "OSType: linux") {
Write-Host "ERROR: Docker is in Linux container mode. Please switch to Windows containers." -ForegroundColor Red
Write-Host "Run: & 'C:\Program Files\Docker\Docker\DockerCli.exe' -SwitchWindowsEngine" -ForegroundColor Yellow
exit 1
}
Write-Host "SUCCESS: Docker is in Windows container mode" -ForegroundColor Green

Write-Host "+++ Running mage package for Windows Docker"
# Set environment for Windows Docker packaging
$env:PLATFORMS = "windows/amd64"
$env:PACKAGES = "docker"

# Run mage targets
$mageTargets = @("clean", "downloadManifest", "packageUsingDRA")
& mage $mageTargets

if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: Mage packaging failed" -ForegroundColor Red
exit $LASTEXITCODE
}

Write-Host "+++ Listing built artifacts"
Get-ChildItem -Recurse build/distributions/ | Format-Table -AutoSize

Write-Host "SUCCESS: Windows Docker packaging completed successfully" -ForegroundColor Green
45 changes: 45 additions & 0 deletions changelog/fragments/1760228817-feature-windows.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# REQUIRED
# Kind can be one of:
# - breaking-change: a change to previously-documented behavior
# - deprecation: functionality that is being removed in a later release
# - bug-fix: fixes a problem in a previous version
# - enhancement: extends functionality but does not break or fix existing behavior
# - feature: new functionality
# - known-issue: problems that we are aware of in a given version
# - security: impacts on the security of a product or a user’s deployment.
# - upgrade: important information for someone upgrading from a prior version
# - other: does not fit into any of the other categories
kind: feature

# REQUIRED for all kinds
# Change summary; a 80ish characters long description of the change.
summary: Add support for Windows containers to enable deployment on Windows hosts

# REQUIRED for breaking-change, deprecation, known-issue
# Long description; in case the summary is not enough to describe the change
# this field accommodate a description without length limits.
# description:

# REQUIRED for breaking-change, deprecation, known-issue
# impact:

# REQUIRED for breaking-change, deprecation, known-issue
# action:

# REQUIRED for all kinds
# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc.
component: elastic-agent

# AUTOMATED
# OPTIONAL to manually add other PR URLs
# PR URL: A link the PR that added the changeset.
# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
# Please provide it if you are adding a fragment for a different PR.
# pr: https://github.com/owner/repo/1234

# AUTOMATED
# OPTIONAL to manually add other issue URLs
# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of).
# If not present is automatically filled by the tooling with the issue linked to the PR number.
# issue: https://github.com/owner/repo/1234
24 changes: 19 additions & 5 deletions dev-tools/mage/dockerbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,34 @@ func (b *dockerBuilder) expandDockerfile(templatesDir string, data map[string]in
dockerfile = f
}

// Use Windows-specific Dockerfile for Windows builds
if b.OS == "windows" {
dockerfile = "Dockerfile.windows.elastic-agent.tmpl"
}

entrypoint := "docker-entrypoint.tmpl"
if e, found := b.ExtraVars["docker_entrypoint"]; found {
entrypoint = e
}

// Use Windows-specific entrypoint for Windows builds
if b.OS == "windows" {
entrypoint = "docker-entrypoint.windows.elastic-agent.tmpl"
}

type fileExpansion struct {
source string
target string
}
for _, file := range []fileExpansion{{dockerfile, "Dockerfile.tmpl"}, {entrypoint, "docker-entrypoint.tmpl"}} {
target := strings.TrimSuffix(
filepath.Join(b.buildDir, file.target),
".tmpl",
)

targetDockerfile := "Dockerfile"
targetEntrypoint := "docker-entrypoint"
if b.OS == "windows" {
targetEntrypoint = "docker-entrypoint.ps1"
}

for _, file := range []fileExpansion{{dockerfile, targetDockerfile}, {entrypoint, targetEntrypoint}} {
target := filepath.Join(b.buildDir, file.target)
path := filepath.Join(templatesDir, file.source)
err := b.ExpandFile(path, target, data)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions dev-tools/mage/pkgtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ var OSArchNames = map[string]map[PackageType]map[string]string{
"amd64": "x86_64",
"arm64": "arm64",
},
Docker: {
"amd64": "amd64",
},
},
"darwin": {
TarGz: {
Expand Down
36 changes: 36 additions & 0 deletions dev-tools/packaging/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,11 @@ shared:
extra_vars:
from: 'docker.elastic.co/wolfi/chainguard-base-fips:latest'

- &docker_windows_spec
docker_variant: 'basic'
extra_vars:
from: '--platform=windows/amd64 mcr.microsoft.com/powershell:lts-nanoserver-ltsc2022'

- &docker_elastic_spec
extra_vars:
repository: 'docker.elastic.co/elastic-agent'
Expand Down Expand Up @@ -551,6 +556,23 @@ shared:
source: '{{ repo.RootDir }}/deploy/kubernetes/elastic-agent-standalone/templates.d'
mode: 0755

- &agent_windows_docker_spec
<<: *agent_windows_binary_spec
extra_vars:
dockerfile: 'Dockerfile.windows.elastic-agent.tmpl'
docker_entrypoint: 'docker-entrypoint.windows.elastic-agent.tmpl'
user: '{{ .BeatName }}'
beats_install_path: "install"
files:
'elastic-agent.yml':
source: 'elastic-agent.docker.yml'
mode: 0600
config: true
'.elastic-agent.active.commit':
content: >
{{ commit }}
mode: 0644

# cloud build to beats-ci repository
- &agent_docker_cloud_spec
docker_variant: 'cloud'
Expand Down Expand Up @@ -1213,6 +1235,20 @@ specs:
{{ agent_package_version }}
mode: 0644

######## Windows Docker images #########
- os: windows
arch: amd64
types: [docker]
spec:
<<: *docker_windows_spec
<<: *agent_windows_docker_spec
<<: *docker_elastic_spec
<<: *elastic_license_for_binaries
files:
'{{.BeatName}}{{.BinaryExt}}':
source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}}
######## End Windows Docker images #########

- os: darwin
types: [tgz]
spec:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{{- $beatHome := printf "C:/%s" .BeatName }}
{{- $repoInfo := repo }}

FROM {{ .from }}

ENV BEAT_SETUID_AS={{ .user }}

LABEL \
org.label-schema.build-date="{{ date }}" \
org.label-schema.schema-version="1.0" \
org.label-schema.vendor="{{ .BeatVendor }}" \
org.label-schema.license="{{ .License }}" \
org.label-schema.name="{{ .BeatName }}" \
org.label-schema.version="{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}" \
org.label-schema.url="{{ .BeatURL }}" \
org.label-schema.vcs-url="{{ $repoInfo.RootImportPath }}" \
org.label-schema.vcs-ref="{{ commit }}" \
io.k8s.description="{{ .BeatDescription }}" \
io.k8s.display-name="{{ .BeatName | title }} image" \
org.opencontainers.image.created="{{ date }}" \
org.opencontainers.image.licenses="{{ .License }}" \
org.opencontainers.image.title="{{ .BeatName | title }}" \
org.opencontainers.image.vendor="{{ .BeatVendor }}" \
org.opencontainers.image.authors="[email protected]" \
maintainer="[email protected]" \
name="{{ .BeatName }}" \
vendor="{{ .BeatVendor }}" \
version="{{ agent_package_version }}{{if .Snapshot}}-SNAPSHOT{{end}}" \
release="1" \
url="{{ .BeatURL }}" \
summary="{{ .BeatName }}" \
license="{{ .License }}" \
description="{{ .BeatDescription }}"

ENV ELASTIC_CONTAINER="true"
ENV PATH="{{ $beatHome }};C:/Windows/system32;C:/Windows"
ENV GODEBUG="madvdontneed=1"

# Copy the agent files
COPY beat {{ $beatHome }}

# Copy the entrypoint script
COPY docker-entrypoint.ps1 C:/docker-entrypoint.ps1

# Create necessary directories using cmd (nanoserver has limited PowerShell)
RUN cmd /S /C "mkdir {{ $beatHome }}\data 2>nul & mkdir C:\licenses 2>nul & exit 0"

# Copy license files
RUN cmd /S /C "if exist {{ $beatHome }}\LICENSE.txt copy {{ $beatHome }}\LICENSE.txt C:\licenses\LICENSE.txt"
RUN cmd /S /C "if exist {{ $beatHome }}\NOTICE.txt copy {{ $beatHome }}\NOTICE.txt C:\licenses\NOTICE.txt"

{{- range $i, $port := .ExposePorts }}
EXPOSE {{ $port }}
{{- end }}

# When running under Docker, we must ensure libbeat monitoring pulls cgroup
# metrics from the proper location (not applicable to Windows but kept for consistency)
ENV LIBBEAT_MONITORING_CGROUPS_HIERARCHY_OVERRIDE=/

WORKDIR {{ $beatHome }}

# Use PowerShell Core with full path from PowerShell nanoserver image
ENTRYPOINT ["C:/Program Files/PowerShell/pwsh.exe", "-NoProfile", "-File", "C:/docker-entrypoint.ps1"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# PowerShell entrypoint for Elastic Agent Windows containers
# Equivalent to docker-entrypoint.elastic-agent.tmpl for Linux

# For information on the possible environment variables that can be passed into the container, run:
# .\{{ .BeatName }}.exe container --help

$ErrorActionPreference = "Stop"

if ($env:ELASTIC_AGENT_OTEL -eq "true") {
& "{{ .BeatName }}.exe" otel $args
} else {
& "{{ .BeatName }}.exe" container $args
}

exit $LASTEXITCODE