Skip to content

Commit 64dd895

Browse files
Merge pull request #47 from CheckmarxDev/health-role
Implement different health check execution based on role
2 parents b8c9a7e + e4b9fea commit 64dd895

File tree

11 files changed

+314
-65
lines changed

11 files changed

+314
-65
lines changed

cmd/main.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,33 @@ func main() {
4747
exitIfError(err)
4848
sastrm := viper.GetString(sastRmPathKey)
4949

50-
err = bindKeyToEnvAndDefault(params.AstWebAppHealthCheckPathKey, params.AstWebAppHealthCheckPathEnv, "/health-check")
50+
err = bindKeyToEnvAndDefault(params.AstWebAppHealthCheckPathKey, params.AstWebAppHealthCheckPathEnv, "#/projects")
5151
exitIfError(err)
5252
webAppHlthChk := viper.GetString(params.AstWebAppHealthCheckPathKey)
5353

54+
err = bindKeyToEnvAndDefault(params.HealthcheckPathKey, params.HealthcheckPathEnv, "api/healthcheck")
55+
exitIfError(err)
56+
healthcheck := viper.GetString(params.HealthcheckPathKey)
57+
58+
err = bindKeyToEnvAndDefault(params.HealthcheckDBPathKey, params.HealthcheckDBPathEnv, "database")
59+
exitIfError(err)
60+
healthcheckDBPath := viper.GetString(params.HealthcheckDBPathKey)
61+
62+
err = bindKeyToEnvAndDefault(params.HealthcheckMessageQueuePathKey,
63+
params.HealthcheckMessageQueuePathEnv, "message-queue")
64+
exitIfError(err)
65+
healthcheckMessageQueuePath := viper.GetString(params.HealthcheckMessageQueuePathKey)
66+
67+
err = bindKeyToEnvAndDefault(params.HealthcheckObjectStorePathKey,
68+
params.HealthcheckObjectStorePathEnv, "object-store")
69+
exitIfError(err)
70+
healthcheckObjectStorePath := viper.GetString(params.HealthcheckObjectStorePathKey)
71+
72+
err = bindKeyToEnvAndDefault(params.HealthcheckInMemoryDBPathKey,
73+
params.HealthcheckInMemoryDBPathEnv, "in-memory-db")
74+
exitIfError(err)
75+
healthcheckInMemoryDBPath := viper.GetString(params.HealthcheckInMemoryDBPathKey)
76+
5477
err = bindKeyToEnvAndDefault(params.AccessKeyIDConfigKey, params.AccessKeyIDEnv, "")
5578
exitIfError(err)
5679

@@ -76,14 +99,25 @@ func main() {
7699
sastrmURL := fmt.Sprintf("%s/%s", ast, sastrm)
77100
bflURL := fmt.Sprintf("%s/%s", ast, bfl)
78101
webAppHlthChkURL := fmt.Sprintf("%s/%s", ast, webAppHlthChk)
102+
hlthChekURL := fmt.Sprintf("%s/%s", ast, healthcheck)
103+
healthcheckDBURL := fmt.Sprintf("%s/%s", hlthChekURL, healthcheckDBPath)
104+
healthcheckNatsURL := fmt.Sprintf("%s/%s", hlthChekURL, healthcheckMessageQueuePath)
105+
healthcheckMinioURL := fmt.Sprintf("%s/%s", hlthChekURL, healthcheckObjectStorePath)
106+
healthcheckRedisURL := fmt.Sprintf("%s/%s", hlthChekURL, healthcheckInMemoryDBPath)
79107

80108
scansWrapper := wrappers.NewHTTPScansWrapper(scansURL)
81109
uploadsWrapper := wrappers.NewUploadsHTTPWrapper(uploadsURL)
82110
projectsWrapper := wrappers.NewHTTPProjectsWrapper(projectsURL)
83111
resultsWrapper := wrappers.NewHTTPResultsWrapper(resultsURL)
84112
bflWrapper := wrappers.NewHTTPBFLWrapper(bflURL)
85113
rmWrapper := wrappers.NewSastRmHTTPWrapper(sastrmURL)
86-
healthCheckWrapper := wrappers.NewHTTPHealthCheckWrapper(webAppHlthChkURL)
114+
healthCheckWrapper := wrappers.NewHealthCheckHTTPWrapper(
115+
webAppHlthChkURL,
116+
healthcheckDBURL,
117+
healthcheckNatsURL,
118+
healthcheckMinioURL,
119+
healthcheckRedisURL,
120+
)
87121
defaultConfigFileLocation := "/etc/conf/cx/config.yml"
88122

89123
astCli := commands.NewAstCLI(

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/checkmarxDev/ast-cli
33
go 1.13
44

55
require (
6+
github.com/checkmarxDev/healthcheck v1.1.0
67
github.com/checkmarxDev/sast-rm v1.1.1
78
github.com/checkmarxDev/scans v1.3.0
89
github.com/checkmarxDev/uploads v1.0.1

go.sum

Lines changed: 51 additions & 0 deletions
Large diffs are not rendered by default.

internal/commands/health.go

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package commands
22

33
import (
44
"fmt"
5+
"sync"
56

6-
"github.com/pkg/errors"
7+
commonParams "github.com/checkmarxDev/ast-cli/internal/params"
8+
"github.com/spf13/viper"
79

810
"github.com/checkmarxDev/ast-cli/internal/wrappers"
911
"github.com/spf13/cobra"
@@ -12,23 +14,56 @@ import (
1214
func NewHealthCheckCommand(healthCheckWrapper wrappers.HealthCheckWrapper) *cobra.Command {
1315
return &cobra.Command{
1416
Use: "health-check",
15-
Short: "Run health check",
16-
RunE: runAllHealthChecks(healthCheckWrapper),
17+
Short: "Run AST health check",
18+
Run: runAllHealthChecks(healthCheckWrapper),
1719
}
1820
}
1921

20-
func runWebAppHealthCheck(healthCheckWrapper wrappers.HealthCheckWrapper) error {
21-
status, err := healthCheckWrapper.RunWebAppCheck()
22+
func runHealthCheck(c *wrappers.HealthCheck) {
23+
status, err := c.Handler()
2224
if err != nil {
23-
return errors.Wrapf(err, "Web App error")
25+
fmt.Printf("%v error %v\n", c.Name, err)
26+
} else {
27+
fmt.Printf("%v status: %v\n", c.Name, status)
28+
}
29+
}
30+
31+
func runChecksConcurrently(checks []*wrappers.HealthCheck) {
32+
var wg sync.WaitGroup
33+
for _, healthChecker := range checks {
34+
wg.Add(1) //nolint:mnd
35+
go func(c *wrappers.HealthCheck) {
36+
defer wg.Done()
37+
runHealthCheck(c)
38+
}(healthChecker)
39+
}
40+
41+
wg.Wait()
42+
}
43+
44+
func newHealthChecksByRole(h wrappers.HealthCheckWrapper, role string) (checksByRole []*wrappers.HealthCheck) {
45+
sastRoles := [...]string{commonParams.SastALlInOne, commonParams.SastEngine, commonParams.SastManager}
46+
sastAndScaRoles := append(sastRoles[:], commonParams.ScaAgent)
47+
healthChecks := []*wrappers.HealthCheck{
48+
wrappers.NewHealthCheck("DB", h.RunDBCheck, sastRoles[:]),
49+
wrappers.NewHealthCheck("Web App", h.RunWebAppCheck, sastRoles[:]),
50+
wrappers.NewHealthCheck("In-memory DB", h.RunInMemoryDBCheck, sastAndScaRoles),
51+
wrappers.NewHealthCheck("Object Store", h.RunObjectStoreCheck, sastAndScaRoles),
52+
wrappers.NewHealthCheck("Message Queue", h.RunMessageQueueCheck, sastAndScaRoles),
53+
}
54+
55+
for _, hc := range healthChecks {
56+
if hc.HasRole(role) {
57+
checksByRole = append(checksByRole, hc)
58+
}
2459
}
2560

26-
fmt.Printf("Web App status: %v", status)
27-
return nil
61+
return checksByRole
2862
}
2963

30-
func runAllHealthChecks(healthCheckWrapper wrappers.HealthCheckWrapper) func(cmd *cobra.Command, args []string) error {
31-
return func(cmd *cobra.Command, args []string) error {
32-
return runWebAppHealthCheck(healthCheckWrapper)
64+
func runAllHealthChecks(healthCheckWrapper wrappers.HealthCheckWrapper) func(cmd *cobra.Command, args []string) {
65+
return func(cmd *cobra.Command, args []string) {
66+
hlthChks := newHealthChecksByRole(healthCheckWrapper, viper.GetString(commonParams.AstRoleKey))
67+
runChecksConcurrently(hlthChks)
3368
}
3469
}

internal/commands/health_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// +build !integration
2+
13
package commands
24

35
import (
@@ -6,8 +8,14 @@ import (
68
"gotest.tools/assert"
79
)
810

9-
func TestWebAppHealthCheck(t *testing.T) {
11+
func TestSastWebAppHealthCheck(t *testing.T) {
12+
cmd := createASTTestCommand()
13+
err := executeTestCommand(cmd, "single-node", "health-check", "--role", "SAST_ALL_IN_ONE")
14+
assert.NilError(t, err)
15+
}
16+
17+
func TestScaHealthCheck(t *testing.T) {
1018
cmd := createASTTestCommand()
11-
err := executeTestCommand(cmd, "single-node", "health-check")
19+
err := executeTestCommand(cmd, "single-node", "health-check", "--role", "SCA_AGENT")
1220
assert.NilError(t, err)
1321
}

internal/commands/single_node.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ func NewSingleNodeCommand(healthCheckWrapper wrappers.HealthCheckWrapper, defaul
7474
updateSingleNodeCmd.PersistentFlags().String(astInstallationDir, installationFolderDefault, installationFolderUsage)
7575
updateSingleNodeCmd.PersistentFlags().String(configFileFlag, "", installationConfigFileUsage)
7676

77+
healthSingleNodeCmd.PersistentFlags().String(astRoleFlag, commonParams.ScaAgent, astRoleFlagUsage)
78+
_ = viper.BindPFlag(commonParams.AstRoleKey, healthSingleNodeCmd.PersistentFlags().Lookup(astRoleFlag))
79+
7780
singleNodeCmd.AddCommand(
7881
upSingleNodeCmd,
7982
downSingleNodeCmd,

internal/params/envs.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
package params
22

33
const (
4-
AstURIEnv = "AST_URI"
5-
ScansPathEnv = "SCANS_PATH"
6-
ProjectsPathEnv = "PROJECTS_PATH"
7-
ResultsPathEnv = "RESULTS_PATH"
8-
BflPathEnv = "BFL_PATH"
9-
SastRmPathEnv = "SAST_RM_PATH"
10-
UploadsPathEnv = "UPLOADS_PATH"
11-
CredentialsFilePathEnv = "CREDENTIALS_FILE_PATH"
12-
TokenExpirySecondsEnv = "TOKEN_EXPIRY_SECONDS"
13-
AccessKeyIDEnv = "AST_ACCESS_KEY_ID"
14-
AstAuthenticationURIEnv = "AST_AUTHENTICATION_URI"
15-
AccessKeySecretEnv = "AST_ACCESS_KEY_SECRET"
16-
AstRoleEnv = "AST_ROLE"
17-
AstWebAppHealthCheckPathEnv = "AST_WEB_APP_HEALTH_CHECK_PATH"
4+
AstURIEnv = "AST_URI"
5+
ScansPathEnv = "SCANS_PATH"
6+
ProjectsPathEnv = "PROJECTS_PATH"
7+
ResultsPathEnv = "RESULTS_PATH"
8+
BflPathEnv = "BFL_PATH"
9+
SastRmPathEnv = "SAST_RM_PATH"
10+
UploadsPathEnv = "UPLOADS_PATH"
11+
CredentialsFilePathEnv = "CREDENTIALS_FILE_PATH"
12+
TokenExpirySecondsEnv = "TOKEN_EXPIRY_SECONDS"
13+
AccessKeyIDEnv = "AST_ACCESS_KEY_ID"
14+
AstAuthenticationURIEnv = "AST_AUTHENTICATION_URI"
15+
AccessKeySecretEnv = "AST_ACCESS_KEY_SECRET"
16+
AstRoleEnv = "AST_ROLE"
17+
AstWebAppHealthCheckPathEnv = "AST_WEB_APP_HEALTH_CHECK_PATH"
18+
HealthcheckPathEnv = "HEALTHCHECK_PATH"
19+
HealthcheckDBPathEnv = "HEALTHCHECK_DB_PATH"
20+
HealthcheckMessageQueuePathEnv = "HEALTHCHECK_MESSAGE_QUEUE_PATH"
21+
HealthcheckObjectStorePathEnv = "HEALTHCHECK_OBJECT_STORE_PATH"
22+
HealthcheckInMemoryDBPathEnv = "HEALTHCHECK_IN_MEMORY_DB_PATH"
1823
)

internal/params/keys.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@ package params
33
import "strings"
44

55
var (
6-
AstURIKey = strings.ToLower(AstURIEnv)
7-
ScansPathKey = strings.ToLower(ScansPathEnv)
8-
ProjectsPathKey = strings.ToLower(ProjectsPathEnv)
9-
ResultsPathKey = strings.ToLower(ResultsPathEnv)
10-
BflPathKey = strings.ToLower(BflPathEnv)
11-
UploadsPathKey = strings.ToLower(UploadsPathEnv)
12-
AccessKeyIDConfigKey = strings.ToLower(AccessKeyIDEnv)
13-
AccessKeySecretConfigKey = strings.ToLower(AccessKeySecretEnv)
14-
AstAuthenticationURIConfigKey = strings.ToLower(AstAuthenticationURIEnv)
15-
CredentialsFilePathKey = strings.ToLower(CredentialsFilePathEnv)
16-
TokenExpirySecondsKey = strings.ToLower(TokenExpirySecondsEnv)
17-
AstRoleKey = strings.ToLower(AstRoleEnv)
18-
AstWebAppHealthCheckPathKey = strings.ToLower(AstWebAppHealthCheckPathEnv)
6+
AstURIKey = strings.ToLower(AstURIEnv)
7+
ScansPathKey = strings.ToLower(ScansPathEnv)
8+
ProjectsPathKey = strings.ToLower(ProjectsPathEnv)
9+
ResultsPathKey = strings.ToLower(ResultsPathEnv)
10+
BflPathKey = strings.ToLower(BflPathEnv)
11+
UploadsPathKey = strings.ToLower(UploadsPathEnv)
12+
AccessKeyIDConfigKey = strings.ToLower(AccessKeyIDEnv)
13+
AccessKeySecretConfigKey = strings.ToLower(AccessKeySecretEnv)
14+
AstAuthenticationURIConfigKey = strings.ToLower(AstAuthenticationURIEnv)
15+
CredentialsFilePathKey = strings.ToLower(CredentialsFilePathEnv)
16+
TokenExpirySecondsKey = strings.ToLower(TokenExpirySecondsEnv)
17+
AstRoleKey = strings.ToLower(AstRoleEnv)
18+
AstWebAppHealthCheckPathKey = strings.ToLower(AstWebAppHealthCheckPathEnv)
19+
HealthcheckPathKey = strings.ToLower(HealthcheckPathEnv)
20+
HealthcheckDBPathKey = strings.ToLower(HealthcheckDBPathEnv)
21+
HealthcheckMessageQueuePathKey = strings.ToLower(HealthcheckMessageQueuePathEnv)
22+
HealthcheckObjectStorePathKey = strings.ToLower(HealthcheckObjectStorePathEnv)
23+
HealthcheckInMemoryDBPathKey = strings.ToLower(HealthcheckInMemoryDBPathEnv)
1924
)

internal/wrappers/health-http.go

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,96 @@
11
package wrappers
22

33
import (
4+
"encoding/json"
45
"fmt"
6+
"io"
57
"io/ioutil"
68
"net/http"
79

10+
healthcheckApi "github.com/checkmarxDev/healthcheck/api/rest/v1"
11+
812
errors "github.com/pkg/errors"
913
)
1014

11-
type HealthCheckHTTPWrapper struct {
12-
webAppURL string
15+
type healthCheckHTTPWrapper struct {
16+
WebAppHealthcheckURL string
17+
DBHealthcheckURL string
18+
MessageQueueHealthcheckURL string
19+
ObjectStoreHealthcheckURL string
20+
InMemoryDBHealthcheckURL string
1321
}
1422

15-
func NewHTTPHealthCheckWrapper(astWebAppURL string) HealthCheckWrapper {
16-
return &HealthCheckHTTPWrapper{webAppURL: astWebAppURL}
23+
func parseHealthcheckResponse(body io.ReadCloser) (*HealthStatus, error) {
24+
status := &HealthStatus{}
25+
if err := json.NewDecoder(body).Decode(status); err != nil {
26+
return nil, errors.Wrapf(err, "Failed to parse healthcheck response")
27+
}
28+
29+
return status, nil
1730
}
1831

19-
func (h *HealthCheckHTTPWrapper) RunWebAppCheck() (*HealthStatus, error) {
20-
resp, err := SendHTTPRequest(http.MethodGet, h.webAppURL, nil)
32+
func runHealthCheckRequest(url string,
33+
parser func(body io.ReadCloser) (*HealthStatus, error)) (*HealthStatus, error) {
34+
resp, err := SendHTTPRequest(http.MethodGet, url, nil)
2135
if err != nil {
22-
return nil, errors.Wrapf(err, "Http request %v failed", h.webAppURL)
36+
return nil, errors.Wrapf(err, "Http request %v failed", url)
2337
}
2438

2539
defer resp.Body.Close()
26-
2740
if resp.StatusCode != http.StatusOK {
2841
body, _ := ioutil.ReadAll(resp.Body)
2942
return &HealthStatus{
30-
Success: false,
31-
Message: fmt.Sprintf("HTTP status code %v with body %v", resp.StatusCode, func() string {
32-
if body != nil {
33-
return string(body)
34-
}
35-
36-
return ""
37-
}()),
43+
&healthcheckApi.HealthcheckModel{
44+
Success: false,
45+
Message: fmt.Sprintf("Http request %v responded with status code %v and body %v",
46+
url, resp.StatusCode, func() string {
47+
if body != nil {
48+
return string(body)
49+
}
50+
51+
return ""
52+
}()),
53+
},
3854
}, nil
3955
}
4056

41-
return &HealthStatus{Success: true, Message: ""}, nil
57+
return parser(resp.Body)
58+
}
59+
60+
func NewHealthCheckHTTPWrapper(astWebAppURL, healthDBURL, healthcheckNatsURL,
61+
healthcheckMinioURL, healthCheckRedisURL string) HealthCheckWrapper {
62+
return &healthCheckHTTPWrapper{
63+
astWebAppURL,
64+
healthDBURL,
65+
healthcheckNatsURL,
66+
healthcheckMinioURL,
67+
healthCheckRedisURL,
68+
}
69+
}
70+
71+
func (h *healthCheckHTTPWrapper) RunWebAppCheck() (*HealthStatus, error) {
72+
return runHealthCheckRequest(h.WebAppHealthcheckURL, func(body io.ReadCloser) (*HealthStatus, error) {
73+
return &HealthStatus{
74+
&healthcheckApi.HealthcheckModel{
75+
Success: true,
76+
Message: "",
77+
},
78+
}, nil
79+
})
80+
}
81+
82+
func (h *healthCheckHTTPWrapper) RunDBCheck() (*HealthStatus, error) {
83+
return runHealthCheckRequest(h.DBHealthcheckURL, parseHealthcheckResponse)
84+
}
85+
86+
func (h *healthCheckHTTPWrapper) RunMessageQueueCheck() (*HealthStatus, error) {
87+
return runHealthCheckRequest(h.MessageQueueHealthcheckURL, parseHealthcheckResponse)
88+
}
89+
90+
func (h *healthCheckHTTPWrapper) RunObjectStoreCheck() (*HealthStatus, error) {
91+
return runHealthCheckRequest(h.ObjectStoreHealthcheckURL, parseHealthcheckResponse)
92+
}
93+
94+
func (h *healthCheckHTTPWrapper) RunInMemoryDBCheck() (*HealthStatus, error) {
95+
return runHealthCheckRequest(h.InMemoryDBHealthcheckURL, parseHealthcheckResponse)
4296
}

0 commit comments

Comments
 (0)