diff --git a/README.md b/README.md index ad7304e..16cdd0f 100644 --- a/README.md +++ b/README.md @@ -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 '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 '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 '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 'Ping failed'" +./host_check +``` diff --git a/build.sh b/build.sh index f13c755..45847b6 100644 --- a/build.sh +++ b/build.sh @@ -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() { diff --git a/dist/host_check b/dist/host_check index ea69307..be15532 100755 Binary files a/dist/host_check and b/dist/host_check differ diff --git a/dist/host_check_darwin_arm64 b/dist/host_check_darwin_arm64 new file mode 100755 index 0000000..419eb1e Binary files /dev/null and b/dist/host_check_darwin_arm64 differ diff --git a/dist/host_check_linux_arm b/dist/host_check_linux_arm index 7430251..18a9a1d 100755 Binary files a/dist/host_check_linux_arm and b/dist/host_check_linux_arm differ diff --git a/dist/host_check_linux_arm64 b/dist/host_check_linux_arm64 index 4513534..d849a04 100755 Binary files a/dist/host_check_linux_arm64 and b/dist/host_check_linux_arm64 differ diff --git a/go.mod b/go.mod index f76e398..6800ff1 100644 --- a/go.mod +++ b/go.mod @@ -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 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..34818e4 --- /dev/null +++ b/go.sum @@ -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= diff --git a/host_check.go b/host_check.go index 576ee50..cde7977 100644 --- a/host_check.go +++ b/host_check.go @@ -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, "", 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, "", 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, "", "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 +} +