From 87f5689aebadf57fa3d340ddbe7baf69aca49855 Mon Sep 17 00:00:00 2001 From: Farshad Nematdoust Date: Mon, 17 Feb 2020 22:24:35 +0100 Subject: [PATCH 1/7] Add http check module --- httpChecker/helpers.go | 25 ++++++++++++++++++ httpChecker/httpChecker.go | 54 ++++++++++++++++++++++++++++++++++++++ httpChecker/structs.go | 7 +++++ 3 files changed, 86 insertions(+) create mode 100644 httpChecker/helpers.go create mode 100644 httpChecker/httpChecker.go create mode 100644 httpChecker/structs.go diff --git a/httpChecker/helpers.go b/httpChecker/helpers.go new file mode 100644 index 0000000..a5300da --- /dev/null +++ b/httpChecker/helpers.go @@ -0,0 +1,25 @@ +package httpChecker + +import "net/url" + +func (h *HttpCheck) validateUrl() bool { + _, err := url.ParseRequestURI(h.Url) + if err != nil { + return false + } + + u, err := url.Parse(h.Url) + if err != nil || u.Scheme == "" || u.Host == "" { + return false + } + + return true +} + +func (h *HttpCheck) validateStatusCode() bool { + // check against common status code + if h.Status < 100 || h.Status > 599 { + return false + } + return true +} diff --git a/httpChecker/httpChecker.go b/httpChecker/httpChecker.go new file mode 100644 index 0000000..b91fc42 --- /dev/null +++ b/httpChecker/httpChecker.go @@ -0,0 +1,54 @@ +package httpChecker + +import ( + "errors" + "io/ioutil" + "net/http" + "strings" + "wait4it/model" +) + +func (h *HttpCheck) BuildContext(cx model.CheckContext) { + h.Url = cx.Host + h.Status = cx.HttpConf.StatusCode + if len(cx.HttpConf.Text) > 0 { + h.Text = cx.HttpConf.Text + } +} + +func (h *HttpCheck) Validate() (bool, error) { + if !h.validateUrl() { + return false, errors.New("invalid URL provided") + } + + if !h.validateStatusCode() { + return false, errors.New("invalid status code provided") + } + + return true, nil +} + +func (h *HttpCheck) Check() (bool, bool, error) { + resp, err := http.Get(h.Url) + + if err != nil { + return false, true, err + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return false, true, err + } + + if resp.StatusCode != h.Status { + return false, false, errors.New("invalid status code") + } + + if len(h.Text) > 0 { + if !strings.Contains(string(body), h.Text) { + return false, false, errors.New("can't find substring in response") + } + } + + return true, false, nil +} diff --git a/httpChecker/structs.go b/httpChecker/structs.go new file mode 100644 index 0000000..9f95736 --- /dev/null +++ b/httpChecker/structs.go @@ -0,0 +1,7 @@ +package httpChecker + +type HttpCheck struct { + Url string + Status int + Text string +} From 23031b046b811e97de5dd3e11af1bbac67bd4fab Mon Sep 17 00:00:00 2001 From: Farshad Nematdoust Date: Mon, 17 Feb 2020 22:25:21 +0100 Subject: [PATCH 2/7] Update check context model to support http related fields --- model/check-context-struct.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/model/check-context-struct.go b/model/check-context-struct.go index 6f9a5eb..f2b3112 100644 --- a/model/check-context-struct.go +++ b/model/check-context-struct.go @@ -8,6 +8,7 @@ type CheckContext struct { Password string DatabaseName string DBConf DatabaseSpecificConf + HttpConf HttpSpecificConf } type ConfigurationContext struct { @@ -18,3 +19,7 @@ type ConfigurationContext struct { type DatabaseSpecificConf struct { SSLMode string } +type HttpSpecificConf struct { + StatusCode int + Text string +} From a15b3f9f5e54999518eb79309ad526b191a91e3c Mon Sep 17 00:00:00 2001 From: Farshad Nematdoust Date: Mon, 17 Feb 2020 22:28:51 +0100 Subject: [PATCH 3/7] Update input parser to support new fields --- inputParser/input-parser.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/inputParser/input-parser.go b/inputParser/input-parser.go index 4a90049..98b5659 100644 --- a/inputParser/input-parser.go +++ b/inputParser/input-parser.go @@ -14,6 +14,8 @@ func GetInput() model.CheckContext { password := flag.String("P", "", "Password of the service") databaseName := flag.String("n", "", "Name of the database") sslMode := flag.String("ssl", "disable", "Enable or Disable ssl mode (for some database or services)") + httpCode := flag.Int("status-code", 200, "Status code to be expected from http call") + httpText := flag.String("http-text", "", "Text to check inside http response") flag.Parse() c := model.CheckContext{ @@ -29,6 +31,10 @@ func GetInput() model.CheckContext { DBConf: model.DatabaseSpecificConf{ SSLMode: *sslMode, }, + HttpConf: model.HttpSpecificConf{ + StatusCode: *httpCode, + Text: *httpText, + }, } return c } From 1d60e35bd34400c59682943b6cfcc69e6fd755c1 Mon Sep 17 00:00:00 2001 From: Farshad Nematdoust Date: Mon, 17 Feb 2020 22:29:10 +0100 Subject: [PATCH 4/7] Add http module to supported modules list --- cmd/check-module-list.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/check-module-list.go b/cmd/check-module-list.go index e47aa9c..7a30e4a 100644 --- a/cmd/check-module-list.go +++ b/cmd/check-module-list.go @@ -4,10 +4,12 @@ import ( "wait4it/MySQLChecker" "wait4it/PostgreSQLChecker" "wait4it/TcpChecker" + "wait4it/httpChecker" ) var cm = map[string]interface{}{ "tcp": &TcpChecker.Tcp{}, "mysql": &MySQLChecker.MySQLConnection{}, "postgres": &PostgreSQLChecker.PostgresSQLConnection{}, + "http": &httpChecker.HttpCheck{}, } From a30938efe75f68088a168979a08755279c6bdbf3 Mon Sep 17 00:00:00 2001 From: Farshad Nematdoust Date: Mon, 17 Feb 2020 22:29:20 +0100 Subject: [PATCH 5/7] Update README --- README.md | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b53e0b3..a11c89a 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,16 @@ # wait4it -A simple go application to test whether a port is ready to accept a connection, and also you can check whether your -MySQL or PostgresQL server is ready or not. +A simple go application to test whether a port is ready to accept a connection, or check +MySQL or PostgresQL server is ready or not, Also you can do http call and check the response code and text in response. It also supports **timeout** so it can wait for a particular time and then fail. ## Supported Modules * TCP port * MySQL * PostgresQL +* Http ## Install -You can download the latest release, or you can build it yourself. +You can download the latest [release](https://github.com/ph4r5h4d/wait4it/releases), or you can build it yourself. To build just run `go build -o wait4it` ## Command Line Args @@ -21,6 +22,9 @@ The following command-line flags are supported * u (username for the services that needs username) * P (password for the services that needs password) * n (currently this param is used to identify database name for MySQL) +* ssl (whether to enable or disable ssl-mode for postgres) +* http-status (for Http check, which status code to expect) +* http-text (for Http check, find substring inside the response) ### Sample Check a TCP port @@ -37,6 +41,11 @@ Check a PostgresQL instance ./wait4it -type=postgres -h=127.0.0.1 -p=5432 -t=60 -u=postgres -P=secret -ssl=disable ``` +Check HTTP response and text +```bash +-type=http -h=https://farshad.nematdoust.com -t=60 -status-code=200 -http-text="Software Engineer" +``` + ### Docker You can run this `wait4it` inside a docker container, and it's possible to run this container as init container inside K8s and Openshift. @@ -61,8 +70,20 @@ Check a PostgresQL instance docker run ph4r5h4d/wait4it -type=postgres -h=127.0.0.1 -p=5432 -t=60 -u=postgres -P=secret -ssl=disable ``` +Check HTTP response and text +```bash +docker run ph4r5h4d/wait4it -type=http -h=https://farshad.nematdoust.com -t=60 -status-code=200 -http-text="Software Engineer" +``` + ## Notes #### Exit codes * 0: connection established successfully * 1: timed out * 2: mostly means a validation error or something wrong with the input data + +#### Http check +* for the Http check if you do not define status code it will check for 200 status code +* if `http-text` is not defined then wait4it will just check the status code + +#### Postgres check +* if `ssl` is not defined then it's `disable` by default \ No newline at end of file From df81f84627809f4a9b7644c32987e5528867c8f7 Mon Sep 17 00:00:00 2001 From: Farshad Nematdoust Date: Tue, 18 Feb 2020 10:50:34 +0100 Subject: [PATCH 6/7] Update README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a11c89a..df7583b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # wait4it + +![LICENSE](https://img.shields.io/github/workflow/status/ph4r5h4d/wait4it/Wait4it CI?style=for-the-badge) [![Docker Pull](https://img.shields.io/docker/pulls/ph4r5h4d/wait4it?style=for-the-badge)](https://hub.docker.com/r/ph4r5h4d/wait4it) ![GO Version](https://img.shields.io/github/go-mod/go-version/ph4r5h4d/wait4it?style=for-the-badge) ![TAG](https://img.shields.io/github/v/tag/ph4r5h4d/wait4it?style=for-the-badge) ![LICENSE](https://img.shields.io/github/license/ph4r5h4d/wait4it?style=for-the-badge) + A simple go application to test whether a port is ready to accept a connection, or check MySQL or PostgresQL server is ready or not, Also you can do http call and check the response code and text in response. It also supports **timeout** so it can wait for a particular time and then fail. From 4d9960d1d91581a84e3a6001a98b95ee01671626 Mon Sep 17 00:00:00 2001 From: Farshad Nematdoust Date: Tue, 18 Feb 2020 10:54:06 +0100 Subject: [PATCH 7/7] Update README --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index df7583b..a449e6c 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ ![LICENSE](https://img.shields.io/github/workflow/status/ph4r5h4d/wait4it/Wait4it CI?style=for-the-badge) [![Docker Pull](https://img.shields.io/docker/pulls/ph4r5h4d/wait4it?style=for-the-badge)](https://hub.docker.com/r/ph4r5h4d/wait4it) ![GO Version](https://img.shields.io/github/go-mod/go-version/ph4r5h4d/wait4it?style=for-the-badge) ![TAG](https://img.shields.io/github/v/tag/ph4r5h4d/wait4it?style=for-the-badge) ![LICENSE](https://img.shields.io/github/license/ph4r5h4d/wait4it?style=for-the-badge) -A simple go application to test whether a port is ready to accept a connection, or check -MySQL or PostgresQL server is ready or not, Also you can do http call and check the response code and text in response. +A simple go application to test whether a port is ready to accept a connection or check +MySQL or PostgreSQL server is ready or not, Also you can do Http call and check the response code and text in response. It also supports **timeout** so it can wait for a particular time and then fail. ## Supported Modules @@ -25,7 +25,7 @@ The following command-line flags are supported * u (username for the services that needs username) * P (password for the services that needs password) * n (currently this param is used to identify database name for MySQL) -* ssl (whether to enable or disable ssl-mode for postgres) +* ssl (whether to enable or disable ssl-mode for Postgres) * http-status (for Http check, which status code to expect) * http-text (for Http check, find substring inside the response) @@ -86,7 +86,7 @@ docker run ph4r5h4d/wait4it -type=http -h=https://farshad.nematdoust.com -t=60 - #### Http check * for the Http check if you do not define status code it will check for 200 status code -* if `http-text` is not defined then wait4it will just check the status code +* if `http-text` is not defined then wait4it will check the status code #### Postgres check * if `ssl` is not defined then it's `disable` by default \ No newline at end of file