Skip to content

Commit 685927e

Browse files
pkoutsovasilismergify[bot]
authored andcommitted
[packaging] proxy binary to be for the root dir of windows archive (#7601)
* feat: implement a proxy binary to be placed in the root of windows archive and invoke the nested elastic-agent binary * fix: remove redundant returns in the code * fix: reword error message when we cannot stat inner elastic-agent binary * fix: use slices.Contains to check if we are building for windows/amd64 * fix: add comment to capture that CommitSHA is set at build time * fix: rename hack folder to wrapper * fix: reside typo * fix: reword error message when we cannot stat inner elastic-agent binary * ci: automate go version updates for wrapper/windows/archive-proxy/go.mod * fix: switch logging to fmt and also log to windows event logger * Revert "ci: automate go version updates for wrapper/windows/archive-proxy/go.mod" This reverts commit c9a698b. * fix: initialise windows event log only if we are admin * fix: remove os.Stat call and rely on command.Start() to raise an error if binary is missing * fix: remove custom logger (cherry picked from commit 6b4b0dc) # Conflicts: # dev-tools/packaging/packages.yml
1 parent 7f10040 commit 685927e

File tree

5 files changed

+229
-1
lines changed

5 files changed

+229
-1
lines changed

dev-tools/packaging/packages.yml

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,77 @@ shared:
308308
source: '{{ elastic_beats_dir }}/specs/connectors.spec.yml'
309309
mode: 0644
310310

311+
<<<<<<< HEAD
312+
=======
313+
- &agent_docker_edot_spec
314+
<<: *agent_binary_spec_no_components
315+
docker_variant: 'elastic-otel-collector'
316+
name: 'elastic-otel-collector'
317+
extra_vars:
318+
dockerfile: 'Dockerfile.elastic-agent.tmpl'
319+
docker_entrypoint: 'docker-entrypoint.edot.tmpl'
320+
user: '{{ .BeatName }}'
321+
linux_capabilities: ''
322+
beats_install_path: "install"
323+
files:
324+
'elastic-agent.yml':
325+
source: 'elastic-agent.docker.yml'
326+
mode: 0600
327+
config: true
328+
'otel.yml':
329+
source: 'otel.yml'
330+
mode: 0600
331+
config: true
332+
'.elastic-agent.active.commit':
333+
content: >
334+
{{ commit }}
335+
mode: 0644
336+
'data/{{.BeatName}}-{{ commit_short }}/components/agentbeat.spec.yml':
337+
source: '{{.AgentDropPath}}/{{.GOOS}}-{{.AgentArchName}}.tar.gz/agentbeat.spec.yml'
338+
expand_spec: true
339+
340+
- &agent_docker_edot_wolfi_spec
341+
<<: *agent_docker_edot_spec
342+
docker_variant: 'elastic-otel-collector-wolfi'
343+
name: 'elastic-otel-collector-wolfi'
344+
345+
- &agent_docker_slim_spec
346+
<<: *agent_binary_spec_no_components
347+
docker_variant: 'slim'
348+
extra_vars:
349+
dockerfile: 'Dockerfile.elastic-agent.tmpl'
350+
docker_entrypoint: 'docker-entrypoint.elastic-agent.tmpl'
351+
user: '{{ .BeatName }}'
352+
linux_capabilities: ''
353+
beats_install_path: "install"
354+
files:
355+
'elastic-agent.yml':
356+
source: 'elastic-agent.docker.yml'
357+
mode: 0600
358+
config: true
359+
'otel.yml':
360+
source: 'otel.yml'
361+
mode: 0600
362+
config: true
363+
'.elastic-agent.active.commit':
364+
content: >
365+
{{ commit }}
366+
mode: 0644
367+
'hints.inputs.d':
368+
source: '{{ repo.RootDir }}/deploy/kubernetes/elastic-agent-standalone/templates.d'
369+
mode: 0755
370+
'data/{{.BeatName}}-{{ commit_short }}/components/agentbeat.spec.yml':
371+
source: '{{.AgentDropPath}}/{{.GOOS}}-{{.AgentArchName}}.tar.gz/agentbeat.spec.yml'
372+
expand_spec: true
373+
'data/{{.BeatName}}-{{ commit_short }}/components/pf-host-agent.spec.yml':
374+
source: '{{.AgentDropPath}}/{{.GOOS}}-{{.AgentArchName}}.tar.gz/pf-host-agent.spec.yml'
375+
expand_spec: true
376+
377+
- &agent_docker_slim_wolfi_spec
378+
<<: *agent_docker_slim_spec
379+
docker_variant: 'slim-wolfi'
380+
381+
>>>>>>> 6b4b0dc69 ([packaging] proxy binary to be for the root dir of windows archive (#7601))
311382
# includes nodejs with @elastic/synthetics
312383
- &agent_docker_complete_spec
313384
<<: *agent_docker_spec
@@ -876,7 +947,7 @@ specs:
876947
<<: *elastic_license_for_binaries
877948
files:
878949
'{{.BeatName}}{{.BinaryExt}}':
879-
source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}}
950+
source: ./build/windows-archive-root-binary/elastic-agent-archive-root.exe
880951
'package.version':
881952
content: >
882953
{{ agent_package_version }}

magefile.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,54 @@ func (Build) GenerateConfig() error {
291291
return sh.Copy(filepath.Join(buildDir, configFile), filepath.Join(metaDir, configFile))
292292
}
293293

294+
// WindowsArchiveRootBinary compiles a binary to be placed at the root of the windows elastic-agent archive. This binary
295+
// is a thin proxy to the actual elastic-agent binary that resides in the data/elastic-agent-{commit-short-sha}
296+
// directory of the archive.
297+
func (Build) WindowsArchiveRootBinary() error {
298+
fmt.Println("--- Compiling root binary for windows archive")
299+
hashShort, err := devtools.CommitHashShort()
300+
if err != nil {
301+
return fmt.Errorf("error getting commit hash: %w", err)
302+
}
303+
304+
outputName := "elastic-agent-archive-root"
305+
if runtime.GOOS != "windows" {
306+
// add the .exe extension on non-windows platforms
307+
outputName += ".exe"
308+
}
309+
310+
args := devtools.BuildArgs{
311+
Name: outputName,
312+
OutputDir: filepath.Join(buildDir, "windows-archive-root-binary"),
313+
InputFiles: []string{"wrapper/windows/archive-proxy/main.go"},
314+
CGO: false,
315+
WinMetadata: true,
316+
ExtraFlags: []string{
317+
"-buildmode", "pie", // windows versions inside the support matrix do support position independent code
318+
"-trimpath", // Remove all file system paths from the compiled executable, to improve build reproducibility
319+
},
320+
Vars: map[string]string{
321+
"main.CommitSHA": hashShort,
322+
},
323+
Env: map[string]string{
324+
"GOOS": "windows",
325+
"GOARCH": "amd64",
326+
},
327+
LDFlags: []string{
328+
"-s", // Strip all debug symbols from binary (does not affect Go stack traces).
329+
},
330+
}
331+
332+
if devtools.FIPSBuild {
333+
// there is no actual FIPS relevance for this particular binary
334+
// but better safe than sorry
335+
args.ExtraFlags = append(args.ExtraFlags, "-tags=requirefips")
336+
args.CGO = true
337+
}
338+
339+
return devtools.Build(args)
340+
}
341+
294342
// GolangCrossBuildOSS build the Beat binary inside of the golang-builder.
295343
// Do not use directly, use crossBuild instead.
296344
func GolangCrossBuildOSS() error {
@@ -1006,6 +1054,12 @@ func packageAgent(ctx context.Context, platforms []string, dependenciesVersion s
10061054
log.Println("--- Running post packaging ")
10071055
mg.Deps(Update)
10081056
mg.Deps(agentBinaryTarget, CrossBuildGoDaemon)
1057+
1058+
// compile the elastic-agent.exe proxy binary for the windows archive
1059+
if slices.Contains(platforms, "windows/amd64") {
1060+
mg.Deps(Build.WindowsArchiveRootBinary)
1061+
}
1062+
10091063
mg.SerialDeps(devtools.Package, TestPackages)
10101064
return nil
10111065
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module github.com/elastic/elastic-agent/wrapper/windows/archive-proxy
2+
3+
go 1.24.1
4+
5+
require github.com/elastic/elastic-agent v0.0.0
6+
7+
require golang.org/x/sys v0.31.0 // indirect
8+
9+
replace github.com/elastic/elastic-agent => ../../../
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License 2.0;
3+
// you may not use this file except in compliance with the Elastic License 2.0.
4+
5+
package main
6+
7+
import (
8+
"errors"
9+
"fmt"
10+
"log"
11+
"os"
12+
"os/exec"
13+
"path/filepath"
14+
15+
"github.com/elastic/elastic-agent/pkg/core/process"
16+
)
17+
18+
// CommitSHA is set by the linker at build time
19+
var CommitSHA string
20+
21+
func main() {
22+
log.SetFlags(0)
23+
if CommitSHA == "" {
24+
// this should never happen
25+
log.Fatal("No commit SHA provided\n")
26+
}
27+
28+
exePath, err := os.Executable()
29+
if err != nil {
30+
log.Fatalf("Error getting executable path: %v\n", err)
31+
}
32+
33+
exeAbsPath, err := filepath.Abs(exePath)
34+
if err != nil {
35+
log.Fatalf("Error getting executable absolute path: %v\n", err)
36+
}
37+
38+
// Fabricate the elastic-agent.exe path that resides inside the data/elastic-agent-{commit-short-sha} directory
39+
exeTopPath := filepath.Dir(exeAbsPath)
40+
nestedAgentBinaryPath := filepath.Join(exeTopPath, "data", fmt.Sprintf("elastic-agent-%s", CommitSHA), "elastic-agent.exe")
41+
42+
// Create the arguments
43+
var args []string
44+
if len(os.Args) > 1 {
45+
args = os.Args[1:]
46+
}
47+
48+
g, err := process.CreateJobObject()
49+
if err != nil {
50+
log.Fatalf("Unable to create job object: %v\n", err)
51+
}
52+
defer func() {
53+
_ = g.Close()
54+
}()
55+
56+
// Create the command
57+
command := exec.Command(nestedAgentBinaryPath, args...)
58+
59+
// Forward stdout, stderr, stdin
60+
command.Stdout = os.Stdout
61+
command.Stderr = os.Stderr
62+
command.Stdin = os.Stdin
63+
64+
// Pass the environment
65+
command.Env = os.Environ()
66+
67+
// Run the command
68+
err = command.Start()
69+
if err != nil {
70+
log.Fatalf("Error running command: %v\n", err)
71+
}
72+
73+
// Add the process to the job object
74+
if err := g.Assign(command.Process); err != nil {
75+
log.Fatalf("Error adding job object: %v\n", err)
76+
}
77+
78+
err = command.Wait()
79+
var exitError *exec.ExitError
80+
switch {
81+
case errors.As(err, &exitError):
82+
exitCode := exitError.ExitCode()
83+
if exitCode == 0 {
84+
// Exit with non-zero exit code since we did get an error
85+
os.Exit(1)
86+
}
87+
// Exit with the same exit code
88+
os.Exit(exitCode)
89+
case err != nil:
90+
// Exit with a non-zero exit code
91+
log.Fatalf("Command failed: %v\n", err)
92+
}
93+
}

0 commit comments

Comments
 (0)