Using go entrypoint for Windows agents
This commit is contained in:
parent
0866f929e2
commit
cfdc5b9519
|
|
@ -10,8 +10,6 @@
|
|||
!templates/entrypoints/internal/agent/**
|
||||
!templates/entrypoints/internal/bootstrap/
|
||||
!templates/entrypoints/internal/bootstrap/**
|
||||
!templates/entrypoints/internal/hooks/
|
||||
!templates/entrypoints/internal/hooks/**
|
||||
!templates/entrypoints/licenses/
|
||||
!templates/entrypoints/licenses/go-THIRD-PARTY-NOTICES.txt
|
||||
!templates/config/
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@
|
|||
!templates/entrypoints/internal/agent/**
|
||||
!templates/entrypoints/internal/bootstrap/
|
||||
!templates/entrypoints/internal/bootstrap/**
|
||||
!templates/entrypoints/internal/hooks/
|
||||
!templates/entrypoints/internal/hooks/**
|
||||
!templates/entrypoints/licenses/
|
||||
!templates/entrypoints/licenses/go-THIRD-PARTY-NOTICES.txt
|
||||
!templates/config/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ package main
|
|||
import (
|
||||
config "github.com/zabbix/zabbix-docker/templates/entrypoints/internal/agent"
|
||||
"github.com/zabbix/zabbix-docker/templates/entrypoints/internal/bootstrap"
|
||||
"github.com/zabbix/zabbix-docker/templates/entrypoints/internal/hooks"
|
||||
)
|
||||
|
||||
func prepareService(env bootstrap.Environment) error {
|
||||
|
|
@ -26,10 +25,6 @@ func prepareService(env bootstrap.Environment) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := hooks.Run(env); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.ClearPrivateEnv(env)
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
config "github.com/zabbix/zabbix-docker/templates/entrypoints/internal/agent"
|
||||
"github.com/zabbix/zabbix-docker/templates/entrypoints/internal/bootstrap"
|
||||
"github.com/zabbix/zabbix-docker/templates/entrypoints/internal/hooks"
|
||||
)
|
||||
|
||||
func prepareService(env bootstrap.Environment) error {
|
||||
|
|
@ -34,10 +33,6 @@ func prepareService(env bootstrap.Environment) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := hooks.Run(env); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.ClearPrivateEnv(env)
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
package hooks
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func command(path string, _ os.FileMode) ([]string, bool) {
|
||||
switch strings.ToLower(filepath.Ext(path)) {
|
||||
case ".ps1":
|
||||
return []string{"pwsh.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", path}, true
|
||||
case ".cmd", ".bat":
|
||||
return []string{"cmd.exe", "/D", "/S", "/C", path}, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
//go:build windows
|
||||
|
||||
package hooks
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPowerShellCommand(t *testing.T) {
|
||||
path := `C:\zabbix\entrypoint.d\10-custom.ps1`
|
||||
args, supported := command(path, os.FileMode(0))
|
||||
want := []string{"pwsh.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", path}
|
||||
if !supported || !reflect.DeepEqual(args, want) {
|
||||
t.Fatalf("command() = %#v, %v; want %#v, true", args, supported, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCmdCommand(t *testing.T) {
|
||||
path := `C:\zabbix\entrypoint.d\20-custom.cmd`
|
||||
args, supported := command(path, os.FileMode(0))
|
||||
want := []string{"cmd.exe", "/D", "/S", "/C", path}
|
||||
if !supported || !reflect.DeepEqual(args, want) {
|
||||
t.Fatalf("command() = %#v, %v; want %#v, true", args, supported, want)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
//go:build windows
|
||||
|
||||
// Package hooks runs user-provided scripts from the entrypoint.d directory
|
||||
// before the service starts.
|
||||
package hooks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/zabbix/zabbix-docker/templates/entrypoints/internal/bootstrap"
|
||||
)
|
||||
|
||||
const directoryName = "entrypoint.d"
|
||||
|
||||
// Run executes supported PowerShell and cmd scripts from <home>/entrypoint.d
|
||||
// in file name order. Everything else is skipped. The first failing hook
|
||||
// aborts the entrypoint.
|
||||
func Run(env bootstrap.Environment) error {
|
||||
homeDir, err := bootstrap.RequiredHomeDirectory(env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
directory := filepath.Join(homeDir, directoryName)
|
||||
entries, err := os.ReadDir(directory)
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("read entrypoint hooks directory %s: %w", directory, err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
path := filepath.Join(directory, entry.Name())
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("inspect entrypoint hook %s: %w", path, err)
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
continue
|
||||
}
|
||||
|
||||
args, supported := command(path, info.Mode())
|
||||
if !supported {
|
||||
continue
|
||||
}
|
||||
|
||||
bootstrap.LogInfo("** Running entrypoint hook: %s", path)
|
||||
|
||||
hook := exec.Command(args[0], args[1:]...)
|
||||
hook.Env = env.List()
|
||||
hook.Stdin = os.Stdin
|
||||
hook.Stdout = os.Stdout
|
||||
hook.Stderr = os.Stderr
|
||||
if err := hook.Run(); err != nil {
|
||||
return fmt.Errorf("entrypoint hook %s failed: %w", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
//go:build windows
|
||||
|
||||
package hooks
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/zabbix/zabbix-docker/templates/entrypoints/internal/bootstrap"
|
||||
)
|
||||
|
||||
func TestRunExecutesHooksInOrder(t *testing.T) {
|
||||
homeDir := t.TempDir()
|
||||
directory := filepath.Join(homeDir, directoryName)
|
||||
if err := os.Mkdir(directory, 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
output := filepath.Join(homeDir, "output")
|
||||
for name, content := range map[string]string{
|
||||
"20-second.cmd": "@echo second:%ZABBIX_CONF_DIR%>>\"%HOOK_OUTPUT%\"\r\n",
|
||||
"10-first.cmd": "@echo first:%ZABBIX_CONF_DIR%>>\"%HOOK_OUTPUT%\"\r\n",
|
||||
"30-ignored.txt": "@exit /b 1\r\n",
|
||||
} {
|
||||
if err := os.WriteFile(filepath.Join(directory, name), []byte(content), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
env := bootstrap.NewEnvironment(os.Environ())
|
||||
env["ZABBIX_USER_HOME_DIR"] = homeDir
|
||||
env["ZABBIX_CONF_DIR"] = `C:\zabbix\conf`
|
||||
env["HOOK_OUTPUT"] = output
|
||||
if err := Run(env); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(output)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := strings.ReplaceAll(string(data), "\r\n", "\n")
|
||||
want := "first:C:\\zabbix\\conf\nsecond:C:\\zabbix\\conf\n"
|
||||
if got != want {
|
||||
t.Fatalf("hook output = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunReturnsHookFailure(t *testing.T) {
|
||||
homeDir := t.TempDir()
|
||||
directory := filepath.Join(homeDir, directoryName)
|
||||
if err := os.Mkdir(directory, 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
path := filepath.Join(directory, "10-fail.cmd")
|
||||
if err := os.WriteFile(path, []byte("@exit /b 7\r\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
env := bootstrap.NewEnvironment(os.Environ())
|
||||
env["ZABBIX_USER_HOME_DIR"] = homeDir
|
||||
err := Run(env)
|
||||
if err == nil || !strings.Contains(err.Error(), "10-fail.cmd") {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunIgnoresMissingDirectory(t *testing.T) {
|
||||
err := Run(bootstrap.Environment{"ZABBIX_USER_HOME_DIR": t.TempDir()})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue