This commit is contained in:
Colin 2024-04-18 11:55:01 -04:00
parent 2ec13eb2f9
commit 30701d8910
9 changed files with 96 additions and 65 deletions

View File

@ -1,48 +1,43 @@
# Purpose
This Go binary performs basic network diagnostics on a set of hostnames, useful for checking connectivity to dependency containers.
This Go binary conducts network diagnostics on a set of hostnames, ideal for verifying connectivity to dependent services or containers.
## Usage
1. **Build:**
Execute the build script:
```bash
./build.sh
```
2. **Set Environment Variables:**
* **HOSTNAMES:** Comma-separated list of hostnames to check (e.g., `database,redis-server,api.example.com`)
* **FAIL_ON_ERROR** (optional): Set to "true" to exit the program immediately upon the first ping failure.
* **COMMAND** (optional): Set to "entrypoint.sh" to execute an additional script on each host.
* **ERROR_COMMAND** (optional): A command to execute if a ping failure occurs, useful for automated error reporting (e.g., `go-glitch report-error <hostname> 'Ping failed'`).
* **HOST_CHECK_HOSTNAMES:** Comma-separated list of hostnames to check (e.g., `database,redis-server,api.example.com`).
* **HOST_CHECK_FAIL_ON_ERROR** (optional): Set to "true" to halt execution immediately if a ping to any hostname fails.
* **HOST_CHECK_COMMAND** (optional): Command to execute if all hosts are successfully pinged (e.g., `entrypoint.sh` to run a script on each host).
* **HOST_CHECK_ERROR_COMMAND** (optional): Command to execute if a ping fails, useful for automated error handling (e.g., `go-glitch report-error <hostname> 'Ping failed'`).
3. **Run:**
Start the host check:
```bash
./host_check
```
## Output
For each hostname:
For each hostname, the output includes:
* **DNS Resolution:** Success or failure, with resolved IPs if successful.
* **Ping:** Success or failure, with ping statistics if successful.
* **Custom Script:** Output of the `entrypoint.sh` script, if executed.
* **Error Reporting:** Output of the `ERROR_COMMAND`, if set and a ping failure occurs.
* **DNS Resolution:** Indicates success or failure, displaying resolved IPs if successful.
* **Ping:** Indicates success or failure, including ping statistics if successful.
* **Custom Script:** Displays the output of the `HOST_CHECK_COMMAND` script, if executed.
* **Error Reporting:** Displays the output of the `HOST_CHECK_ERROR_COMMAND`, if a ping failure occurs.
## Example
To check connectivity to "db-container" and "webserver", execute an `entrypoint.sh` script, and report errors to go-glitch:
To verify connectivity to "db-container" and "webserver", execute the `entrypoint.sh` script, and handle errors via go-glitch:
```bash
export HOSTNAMES="db-container,webserver"
export COMMAND="entrypoint.sh"
export ERROR_COMMAND="go-glitch report-error <hostname> 'Ping failed'"
./host_check
```
**Important:**
* Make sure you have a `build.sh` script in your project directory to handle the Go compilation process.
* You'll need an `entrypoint.sh` script if you want to leverage the `COMMAND` functionality.
Let me know if you'd like any other adjustments to your README!
export HOST_CHECK_HOSTNAMES="db-container,webserver"
export HOST_CHECK_COMMAND="entrypoint.sh"
export HOST_CHECK_ERROR_COMMAND="go-glitch report-error <hostname> 'Ping failed'"
./host_check
```

View File

@ -4,7 +4,7 @@
DEFAULT_ARCH="linux/amd64"
# Supported architectures (adjust as needed)
ARCHITECTURES=("linux/amd64" "linux/arm64" "linux/arm/v7")
ARCHITECTURES=("linux/amd64" "linux/arm64" "linux/arm/v7" "darwin/arm64")
# Find the appropriate directory containing Go code (assumes 'src' or project root)
find_go_directory() {

BIN
dist/host_check vendored

Binary file not shown.

BIN
dist/host_check_darwin_arm64 vendored Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

8
go.mod
View File

@ -1,3 +1,11 @@
module git.nixc.us/Nixius/host_check
go 1.21.1
require (
github.com/go-ping/ping v1.1.0 // indirect
github.com/google/uuid v1.2.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.19.0 // indirect
)

16
go.sum Normal file
View File

@ -0,0 +1,16 @@
github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@ -9,66 +9,78 @@ import (
)
func main() {
hostnames := os.Getenv("HOSTNAMES")
hostnames := os.Getenv("HOST_CHECK_HOSTNAMES")
if hostnames == "" {
fmt.Println("Error: Environment variable HOSTNAMES not set or empty.")
fmt.Println("Error: Environment variable HOST_CHECK_HOSTNAMES not set or empty.")
return
}
hosts := strings.Split(hostnames, ",")
hosts := strings.Split(hostnames, ",")
// Environment Variables
failOnError := os.Getenv("FAIL_ON_ERROR") == "true"
commandStr := os.Getenv("COMMAND")
errorCommandStr := os.Getenv("ERROR_COMMAND")
failOnError := os.Getenv("HOST_CHECK_FAIL_ON_ERROR") == "true"
hostCheckCommand := os.Getenv("HOST_CHECK_COMMAND")
errorCommandStr := os.Getenv("HOST_CHECK_ERROR_COMMAND")
allHostsSuccessful := true
for _, host := range hosts {
host = strings.TrimSpace(host)
fmt.Println("\n---", host, "---")
// DNS Resolution (Remove if you don't need this)
ip, err := net.LookupIP(host)
ip, err := net.LookupIP(host)
if err != nil {
fmt.Println("DNS Resolution Failed:", err)
} else {
fmt.Println("Resolved IPs:", ip)
allHostsSuccessful = false
executeCommand(strings.Replace(errorCommandStr, "<hostname>", host, -1)) // Execute error command immediately
if failOnError {
os.Exit(1)
}
continue
}
fmt.Println("Resolved IPs:", ip)
// Ping
pingCmd := exec.Command("ping", "-c", "3", host)
pingOutput, err := pingCmd.Output()
err = executePing(host)
if err != nil {
fmt.Println("Ping Failed:", err)
allHostsSuccessful = false
executeCommand(strings.Replace(errorCommandStr, "<hostname>", host, -1)) // Execute error command immediately
if failOnError {
os.Exit(1)
os.Exit(1)
}
// Execute error command if specified
if errorCommandStr != "" {
cmdParts := strings.Fields(errorCommandStr)
cmd := exec.Command(cmdParts[0], cmdParts[1:]...)
cmdOutput, cmdErr := cmd.Output()
if cmdErr != nil {
fmt.Println("Error Command Execution Failed:", errorCommandStr, cmdErr)
} else {
fmt.Println("Error Command Output:\n", string(cmdOutput))
}
}
} else {
fmt.Println("Ping Output:\n", string(pingOutput))
continue
}
// Execute additional command if specified
if commandStr != "" {
cmdParts := strings.Fields(commandStr)
cmd := exec.Command(cmdParts[0], cmdParts[1:]...)
cmdOutput, err := cmd.Output()
if err != nil {
fmt.Println("Command Execution Failed:", commandStr, err)
} else {
fmt.Println("Command Output:\n", string(cmdOutput))
}
}
fmt.Println("Ping Successful")
}
if !failOnError && allHostsSuccessful && hostCheckCommand != "" {
fmt.Println("Executing HOST_CHECK_COMMAND as all hosts were successful.")
executeCommand(hostCheckCommand)
}
}
func executeCommand(commandStr string) {
if commandStr == "" {
return
}
commandStr = strings.Replace(commandStr, "<hostname>", "the host", -1) // Ensure no placeholder remains
cmdParts := strings.Fields(commandStr)
cmd := exec.Command(cmdParts[0], cmdParts[1:]...)
cmdOutput, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("Command Execution Failed: %s, %v\n", commandStr, err)
} else {
fmt.Printf("Command Output:\n%s\n", string(cmdOutput))
}
}
func executePing(host string) error {
cmd := exec.Command("ping", "-c", "3", host)
cmdOutput, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("Ping Command Output: %s\n", string(cmdOutput))
return err
}
fmt.Printf("Ping Command Output: %s\n", string(cmdOutput))
return nil
}