From 6acfb580dcaefc4833c7f2923e64136dd833ca92 Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Mon, 15 Jan 2018 19:34:07 +0100 Subject: [PATCH] feat(cli): Add CLI flag for health-check (#1366) --- api/cli/cli.go | 7 ++++--- api/cli/defaults.go | 1 + api/cli/defaults_windows.go | 1 + api/cmd/portainer/main.go | 14 ++++++++++++++ api/http/health_check.go | 11 +++++++++++ api/portainer.go | 7 ++++--- build/linux/Dockerfile | 2 ++ 7 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 api/http/health_check.go diff --git a/api/cli/cli.go b/api/cli/cli.go index a343195f4..c9deee9f7 100644 --- a/api/cli/cli.go +++ b/api/cli/cli.go @@ -31,12 +31,12 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) { kingpin.Version(version) flags := &portainer.CLIFlags{ - Endpoint: kingpin.Flag("host", "Dockerd endpoint").Short('H').String(), - ExternalEndpoints: kingpin.Flag("external-endpoints", "Path to a file defining available endpoints").String(), - SyncInterval: kingpin.Flag("sync-interval", "Duration between each synchronization via the external endpoints source").Default(defaultSyncInterval).String(), Addr: kingpin.Flag("bind", "Address and port to serve Portainer").Default(defaultBindAddress).Short('p').String(), Assets: kingpin.Flag("assets", "Path to the assets").Default(defaultAssetsDirectory).Short('a').String(), + CheckHealth: kingpin.Flag("check-health", "GET http://localhost:/api/health endpoint").Default(defaultCheckHeath).Short('c').Bool(), Data: kingpin.Flag("data", "Path to the folder where the data is stored").Default(defaultDataDirectory).Short('d').String(), + Endpoint: kingpin.Flag("host", "Dockerd endpoint").Short('H').String(), + ExternalEndpoints: kingpin.Flag("external-endpoints", "Path to a file defining available endpoints").String(), NoAuth: kingpin.Flag("no-auth", "Disable authentication").Default(defaultNoAuth).Bool(), NoAnalytics: kingpin.Flag("no-analytics", "Disable Analytics in app").Default(defaultNoAnalytics).Bool(), TLSVerify: kingpin.Flag("tlsverify", "TLS support").Default(defaultTLSVerify).Bool(), @@ -46,6 +46,7 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) { SSL: kingpin.Flag("ssl", "Secure Portainer instance using SSL").Default(defaultSSL).Bool(), SSLCert: kingpin.Flag("sslcert", "Path to the SSL certificate used to secure the Portainer instance").Default(defaultSSLCertPath).String(), SSLKey: kingpin.Flag("sslkey", "Path to the SSL key used to secure the Portainer instance").Default(defaultSSLKeyPath).String(), + SyncInterval: kingpin.Flag("sync-interval", "Duration between each synchronization via the external endpoints source").Default(defaultSyncInterval).String(), AdminPassword: kingpin.Flag("admin-password", "Hashed admin password").String(), AdminPasswordFile: kingpin.Flag("admin-password-file", "Path to the file containing the password for the admin user").String(), // Deprecated flags diff --git a/api/cli/defaults.go b/api/cli/defaults.go index 2d350c1c7..6275d3ae1 100644 --- a/api/cli/defaults.go +++ b/api/cli/defaults.go @@ -6,6 +6,7 @@ const ( defaultBindAddress = ":9000" defaultDataDirectory = "/data" defaultAssetsDirectory = "./" + defaultCheckHeath = "false" defaultNoAuth = "false" defaultNoAnalytics = "false" defaultTLSVerify = "false" diff --git a/api/cli/defaults_windows.go b/api/cli/defaults_windows.go index a94657258..7cf861cc3 100644 --- a/api/cli/defaults_windows.go +++ b/api/cli/defaults_windows.go @@ -4,6 +4,7 @@ const ( defaultBindAddress = ":9000" defaultDataDirectory = "C:\\data" defaultAssetsDirectory = "./" + defaultCheckHeath = "false" defaultNoAuth = "false" defaultNoAnalytics = "false" defaultTLSVerify = "false" diff --git a/api/cmd/portainer/main.go b/api/cmd/portainer/main.go index 3c8c9f2aa..efa51c1f3 100644 --- a/api/cmd/portainer/main.go +++ b/api/cmd/portainer/main.go @@ -14,6 +14,7 @@ import ( "github.com/portainer/portainer/ldap" "log" + "os" ) func initCLI() *portainer.CLIFlags { @@ -171,6 +172,19 @@ func retrieveFirstEndpointFromDatabase(endpointService portainer.EndpointService func main() { flags := initCLI() + if *flags.CheckHealth { + statuscode, err := http.HealthCheck(*flags.Addr) + if err == nil { + if statuscode == 200 { + log.Println(*flags.Addr, ": Online - response:", statuscode) + os.Exit(0) + } else { + log.Fatal(*flags.Addr, ": Error - response:", statuscode) + } + } + log.Fatal("Connection error:", err.Error()) + } + fileService := initFileService(*flags.Data) store := initStore(*flags.Data) diff --git a/api/http/health_check.go b/api/http/health_check.go new file mode 100644 index 000000000..08f4623f0 --- /dev/null +++ b/api/http/health_check.go @@ -0,0 +1,11 @@ +package http + +import ( + "net/http" +) + +// HealthCheck GETs /api/status +func HealthCheck(addr string) (int, error) { + resp, err := http.Get("http://" + addr + "/api/status") + return resp.StatusCode, err +} diff --git a/api/portainer.go b/api/portainer.go index 92d2afd9c..8b250009b 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -13,10 +13,10 @@ type ( CLIFlags struct { Addr *string Assets *string + CheckHealth *bool Data *string - ExternalEndpoints *string - SyncInterval *string Endpoint *string + ExternalEndpoints *string NoAuth *bool NoAnalytics *bool TLSVerify *bool @@ -26,12 +26,13 @@ type ( SSL *bool SSLCert *string SSLKey *string + SyncInterval *string AdminPassword *string AdminPasswordFile *string // Deprecated fields + Labels *[]Pair Logo *string Templates *string - Labels *[]Pair } // Status represents the application status. diff --git a/build/linux/Dockerfile b/build/linux/Dockerfile index e16144acc..3bbc694f9 100644 --- a/build/linux/Dockerfile +++ b/build/linux/Dockerfile @@ -9,3 +9,5 @@ WORKDIR / EXPOSE 9000 ENTRYPOINT ["/portainer"] + +HEALTHCHECK --start-period=10ms --interval=30s --timeout=5s --retries=3 CMD ["/portainer", "-c"]