-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
19a24c5
commit a110915
Showing
1 changed file
with
126 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package main | ||
|
||
import ( | ||
|
||
"log" | ||
"net" | ||
"os" | ||
"os/exec" | ||
"os/signal" | ||
"syscall" | ||
"time" | ||
) | ||
const MaximumWaitForProcessStart = 5 * time.Second | ||
|
||
func main() { | ||
// Define the paths and commands from the systemd unit file. | ||
prefix := "/opt/google-cloud-ops-agent" // @PREFIX@ | ||
sysconfdir := "/etc" // @SYSCONFDIR@ | ||
logsDirectory := "google-cloud-ops-agent" | ||
fluentBitStateDiectory := "google-cloud-ops-agent/fluent-bit" | ||
//fluentBitRuntimeDirectory := "google-cloud-ops-agent-fluent-bit" | ||
|
||
|
||
// Wait for network to be online before starting the process | ||
waitForNetwork() | ||
// Start google-cloud-ops-agent.service | ||
|
||
// Starting ExecStartPre commands | ||
execStartPreCmd := exec.Command( | ||
prefix+"/libexec/google_cloud_ops_agent_engine", | ||
"-in", sysconfdir+"/google-cloud-ops-agent/config.yaml", | ||
) | ||
if err := runCommand(execStartPreCmd); err != nil { | ||
log.Fatalf("config validation faile: ", err) | ||
} | ||
|
||
execStartPreFluentBitCmd := exec.Command( | ||
prefix+"/libexec/google_cloud_ops_agent_engine", | ||
"-service", "fluentbit", | ||
"-in", sysconfdir+"/google-cloud-ops-agent/config.yaml", | ||
"-logs", logsDirectory, "-state", fluentBitStateDiectory) | ||
|
||
if err := runCommand(execStartPreFluentBitCmd); err != nil { | ||
log.Fatalf("exec pre command for FluentBit faile: ", err) | ||
} | ||
|
||
execStartPreOtelCmd := exec.Command( | ||
prefix+"/libexec/google_cloud_ops_agent_engine", | ||
"-service", "otel", | ||
"-in", sysconfdir+"/google-cloud-ops-agent/config.yaml", | ||
"-logs", logsDirectory) | ||
|
||
if err := runCommand(execStartPreOtelCmd); err != nil { | ||
log.Fatalf("exec pre command for Otel faile: ", err) | ||
} | ||
|
||
|
||
// Starting Diagnostics Service | ||
execDiagnosticsCmd := exec.Command( | ||
prefix+"/libexec/google_cloud_ops_agent_diagnostics", | ||
"-config", sysconfdir+"/google-cloud-ops-agent/config.yaml", | ||
) | ||
|
||
restartCommand(execDiagnosticsCmd) | ||
|
||
} | ||
|
||
|
||
|
||
func handleSignals(cmd *exec.Cmd) { | ||
// Relay signals that should be passed down to the subprocess we are wrapping. | ||
sigs := make(chan os.Signal, 1) | ||
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT, syscall.SIGCONT) | ||
for { | ||
sig := <-sigs | ||
start := time.Now() | ||
// It is possible that we receive a signal before the code for `cmd.Run()` set cmd.Process. | ||
// In this case we wait up to MaximumWaitForProcessStart before giving up relaying the signal. | ||
for { | ||
if cmd.Process != nil { | ||
cmd.Process.Signal(sig) | ||
break | ||
} else if time.Until(start.Add(MaximumWaitForProcessStart)) <= 0 { | ||
// We waited MaximumWaitForProcessStart and the subprocess did not start. Give up on relaying the signal. | ||
log.Printf("Failed to relay signal %v to subprocess as it has not started yet", sig) | ||
break | ||
} | ||
time.Sleep(50 * time.Millisecond) | ||
} | ||
} | ||
} | ||
|
||
func runCommand(cmd *exec.Cmd) error { | ||
cmd.SysProcAttr = &syscall.SysProcAttr{ | ||
Pdeathsig: syscall.SIGKILL, | ||
Setpgid: true, | ||
} | ||
go handleSignals(cmd) | ||
return cmd.Run() | ||
} | ||
|
||
func restartCommand(cmd *exec.Cmd) { | ||
cmdToRestart := exec.Command(cmd.Path, cmd.Args...) | ||
if err := runCommand(cmdToRestart); err != nil { | ||
log.Fatalf("command failed: ", err) | ||
} else { | ||
log.Print("command succeeded") | ||
} | ||
log.Print("Restarting command") | ||
|
||
restartCommand(cmdToRestart) | ||
} | ||
|
||
func waitForNetwork() { | ||
for { | ||
// Try to connect to a known reliable host (e.g., Google DNS) | ||
conn, err := net.DialTimeout("tcp", "8.8.8.8:53", 5*time.Second) | ||
if err == nil { | ||
conn.Close() | ||
log.Print("Network online. Proceeding...") | ||
break | ||
} | ||
log.Print("Waiting for network...") | ||
time.Sleep(5 * time.Second) | ||
} | ||
} |