Skip to content

Commit

Permalink
requirements:bugfix - now returns error instead of panicking when fail (
Browse files Browse the repository at this point in the history
#856)

Signed-off-by: Ian Cardoso <ian.cardoso@zup.com.br>
  • Loading branch information
iancardosozup authored Dec 17, 2021
1 parent 83dd38d commit f9eedd9
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 111 deletions.
19 changes: 13 additions & 6 deletions cmd/app/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ type Prompt interface {
// Requirements is the interface that validate Horusec dynamic
// requirements to execute analysis
type Requirements interface {
ValidateDocker()
ValidateGit()
ValidateDocker() error
ValidateGit() error
}

type Start struct {
Expand Down Expand Up @@ -319,20 +319,27 @@ func (s *Start) validateConfig() error {
return err
}

s.validateRequirements()
if err := s.validateRequirements(); err != nil {
return err
}

logger.LogDebugWithLevel(messages.MsgDebugShowConfigs + string(s.configs.Bytes()))
return nil
}

func (s *Start) validateRequirements() {
func (s *Start) validateRequirements() error {
if s.configs.EnableGitHistoryAnalysis {
s.requirements.ValidateGit()
if err := s.requirements.ValidateGit(); err != nil {
return err
}
}

if !s.configs.DisableDocker {
s.requirements.ValidateDocker()
if err := s.requirements.ValidateDocker(); err != nil {
return err
}
}
return nil
}

func (s *Start) isRunPromptQuestion(cmd *cobra.Command) bool {
Expand Down
99 changes: 69 additions & 30 deletions cmd/app/start/start_test.go

Large diffs are not rendered by default.

41 changes: 18 additions & 23 deletions internal/controllers/requirements/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,41 +39,36 @@ var (
ErrDockerNotInstalled = errors.New("docker not found. Please check and try again")
)

type RequirementDocker struct{}

func NewRequirementDocker() *RequirementDocker {
return &RequirementDocker{}
}

func (r *RequirementDocker) ValidateDocker() error {
response, err := r.validateIfDockerIsInstalled()
func Validate() error {
response, err := validateIfDockerIsInstalled()
if err != nil {
return err
}
return r.validateIfDockerIsSupported(response)
return validateIfDockerIsSupported(response)
}

func (r *RequirementDocker) validateIfDockerIsInstalled() (string, error) {
response, err := r.execDockerVersion()
func validateIfDockerIsInstalled() (string, error) {
response, err := execDockerVersion()
if err != nil {
logger.LogInfo(messages.MsgInfoHowToInstallDocker)
return "", err
}
if !r.checkIfContainsDockerVersion(response) {

if !checkIfContainsDockerVersion(response) {
return "", ErrDockerNotInstalled
}
return response, r.checkIfDockerIsRunning()
return response, checkIfDockerIsRunning()
}

func (r *RequirementDocker) validateIfDockerIsSupported(version string) error {
err := r.validateIfDockerIsRunningInMinVersion(version)
func validateIfDockerIsSupported(version string) error {
err := validateIfDockerIsRunningInMinVersion(version)
if err != nil {
return err
}
return nil
}

func (r *RequirementDocker) execDockerVersion() (string, error) {
func execDockerVersion() (string, error) {
responseBytes, err := exec.Command("docker", "-v").CombinedOutput()
if err != nil {
logger.LogErrorWithLevel(
Expand All @@ -83,7 +78,7 @@ func (r *RequirementDocker) execDockerVersion() (string, error) {
return strings.ToLower(string(responseBytes)), nil
}

func (r *RequirementDocker) checkIfDockerIsRunning() error {
func checkIfDockerIsRunning() error {
responseBytes, err := exec.Command("docker", "ps").CombinedOutput()
if err != nil {
logger.LogErrorWithLevel(
Expand All @@ -92,8 +87,8 @@ func (r *RequirementDocker) checkIfDockerIsRunning() error {
return err
}

func (r *RequirementDocker) validateIfDockerIsRunningInMinVersion(response string) error {
version, subversion, err := r.extractDockerVersionFromString(response)
func validateIfDockerIsRunningInMinVersion(response string) error {
version, subversion, err := extractDockerVersionFromString(response)
if err != nil {
logger.LogErrorWithLevel(messages.MsgErrorWhenDockerIsLowerVersion, ErrMinVersion)
return err
Expand All @@ -108,19 +103,19 @@ func (r *RequirementDocker) validateIfDockerIsRunningInMinVersion(response strin
return nil
}

func (r *RequirementDocker) extractDockerVersionFromString(response string) (int, int, error) {
func extractDockerVersionFromString(response string) (int, int, error) {
responseSpited := strings.Split(strings.ToLower(response), "docker version ")
if len(responseSpited) < 1 || len(responseSpited) > 1 && len(responseSpited[1]) < 8 {
return 0, 0, ErrDockerNotInstalled
}
return r.getVersionAndSubVersion(responseSpited[1])
return getVersionAndSubVersion(responseSpited[1])
}

func (r *RequirementDocker) checkIfContainsDockerVersion(response string) bool {
func checkIfContainsDockerVersion(response string) bool {
return strings.Contains(strings.ToLower(response), "docker version ")
}

func (r *RequirementDocker) getVersionAndSubVersion(fullVersion string) (int, int, error) {
func getVersionAndSubVersion(fullVersion string) (int, int, error) {
version, err := strconv.Atoi(fullVersion[0:2])
if err != nil {
return 0, 0, ErrDockerNotInstalled
Expand Down
37 changes: 16 additions & 21 deletions internal/controllers/requirements/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,41 +42,36 @@ var (
ErrGitLowerVersion = errors.New("git version is lower of 2.01. Please check and try again")
)

type RequirementGit struct{}

func NewRequirementGit() *RequirementGit {
return &RequirementGit{}
}

func (r *RequirementGit) ValidateGit() error {
response, err := r.validateIfGitIsInstalled()
func Validate() error {
response, err := validateIfGitIsInstalled()
if err != nil {
return err
}
return r.validateIfGitIsSupported(response)
return validateIfGitIsSupported(response)
}

func (r *RequirementGit) validateIfGitIsInstalled() (string, error) {
response, err := r.execGitVersion()
func validateIfGitIsInstalled() (string, error) {
response, err := execGitVersion()
if err != nil {
return "", err
}
if !r.checkIfContainsGitVersion(response) {

if !checkIfContainsGitVersion(response) {
return "", ErrGitNotInstalled
}
return response, nil
}

func (r *RequirementGit) validateIfGitIsSupported(version string) error {
err := r.validateIfGitIsRunningInMinVersion(version)
func validateIfGitIsSupported(version string) error {
err := validateIfGitIsRunningInMinVersion(version)
if err != nil {
logger.LogInfo(messages.MsgInfoHowToInstallGit)
return err
}
return nil
}

func (r *RequirementGit) execGitVersion() (string, error) {
func execGitVersion() (string, error) {
responseBytes, err := exec.Command("git", "--version").CombinedOutput()
if err != nil {
logger.LogErrorWithLevel(messages.MsgErrorWhenCheckRequirementsGit, err)
Expand All @@ -85,8 +80,8 @@ func (r *RequirementGit) execGitVersion() (string, error) {
return strings.ToLower(string(responseBytes)), nil
}

func (r *RequirementGit) validateIfGitIsRunningInMinVersion(response string) error {
version, subversion, err := r.extractGitVersionFromString(response)
func validateIfGitIsRunningInMinVersion(response string) error {
version, subversion, err := extractGitVersionFromString(response)
if err != nil {
return err
}
Expand All @@ -100,19 +95,19 @@ func (r *RequirementGit) validateIfGitIsRunningInMinVersion(response string) err
return nil
}

func (r *RequirementGit) extractGitVersionFromString(response string) (int, int, error) {
func extractGitVersionFromString(response string) (int, int, error) {
responseSpited := strings.Split(strings.ToLower(response), "git version ")
if len(responseSpited) < 1 || len(responseSpited) > 1 && len(responseSpited[1]) < 3 {
return 0, 0, ErrGitNotInstalled
}
return r.getVersionAndSubVersion(responseSpited[1])
return getVersionAndSubVersion(responseSpited[1])
}

func (r *RequirementGit) checkIfContainsGitVersion(response string) bool {
func checkIfContainsGitVersion(response string) bool {
return strings.Contains(strings.ToLower(response), "git version ")
}

func (r *RequirementGit) getVersionAndSubVersion(fullVersion string) (int, int, error) {
func getVersionAndSubVersion(fullVersion string) (int, int, error) {
version, err := strconv.Atoi(fullVersion[0:1])
if err != nil {
return 0, 0, ErrGitNotInstalled
Expand Down
29 changes: 9 additions & 20 deletions internal/controllers/requirements/requirements.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,28 @@
package requirements

import (
"errors"

"github.com/ZupIT/horusec-devkit/pkg/utils/logger"

"github.com/ZupIT/horusec/internal/controllers/requirements/docker"
"github.com/ZupIT/horusec/internal/controllers/requirements/git"
"github.com/ZupIT/horusec/internal/helpers/messages"
)

var ErrRequirements = errors.New("check the requirements for run and try again")
type ValidationFn func() error

type Requirements struct {
gitRequirements *git.RequirementGit
dockerRequirements *docker.RequirementDocker
gitValidationFn ValidationFn
dockerValidationFn ValidationFn
}

func NewRequirements() *Requirements {
return &Requirements{
gitRequirements: git.NewRequirementGit(),
dockerRequirements: docker.NewRequirementDocker(),
gitValidationFn: git.Validate,
dockerValidationFn: docker.Validate,
}
}

func (r *Requirements) ValidateDocker() {
err := r.dockerRequirements.ValidateDocker()
if err != nil {
logger.LogPanicWithLevel(messages.MsgPanicDockerRequirementsToRunHorusec, ErrRequirements)
}
func (r *Requirements) ValidateDocker() error {
return r.dockerValidationFn()
}

func (r *Requirements) ValidateGit() {
err := r.gitRequirements.ValidateGit()
if err != nil {
logger.LogPanicWithLevel(messages.MsgPanicGitRequirementsToRunHorusec, ErrRequirements)
}
func (r *Requirements) ValidateGit() error {
return r.gitValidationFn()
}
12 changes: 5 additions & 7 deletions internal/controllers/requirements/requirements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,12 @@ import (
"github.com/stretchr/testify/assert"
)

func TestValidateRequirements(t *testing.T) {
func TestValidateAllRequirements(t *testing.T) {
t.Run("should return no error when everything it is ok", func(t *testing.T) {
controller := NewRequirements()
assert.NotPanics(t, func() {
controller.ValidateDocker()
})
assert.NotPanics(t, func() {
controller.ValidateGit()
})
err := controller.ValidateGit()
assert.NoError(t, err)
err = controller.ValidateDocker()
assert.NoError(t, err)
})
}
11 changes: 7 additions & 4 deletions internal/utils/testutil/requirements_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package testutil

import (
mockutils "github.com/ZupIT/horusec-devkit/pkg/utils/mock"
"github.com/stretchr/testify/mock"
)

Expand All @@ -26,10 +27,12 @@ func NewRequirementsMock() *RequirementsMock {
return new(RequirementsMock)
}

func (m *RequirementsMock) ValidateDocker() {
_ = m.MethodCalled("ValidateDocker")
func (m *RequirementsMock) ValidateDocker() error {
args := m.MethodCalled("ValidateDocker")
return mockutils.ReturnNilOrError(args, 0)
}

func (m *RequirementsMock) ValidateGit() {
_ = m.MethodCalled("ValidateGit")
func (m *RequirementsMock) ValidateGit() error {
args := m.MethodCalled("ValidateGit")
return mockutils.ReturnNilOrError(args, 0)
}

0 comments on commit f9eedd9

Please sign in to comment.