Skip to content

Commit

Permalink
Introduce install type (#204)
Browse files Browse the repository at this point in the history
* minor refactor

* introduce install type

* remove duplicate log

* remove getTool func

* add version to log

* check go installation

* misc fix

---------

Co-authored-by: sandeep <8293321+ehsandeep@users.noreply.github.com>
  • Loading branch information
dogancanbakir and ehsandeep authored Oct 11, 2023
1 parent 593fd8f commit 0aec3a0
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/setup-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:

- name: Checking tools existence
run: |
go run . | grep -vz "not installed"
go run . | grep -v "not installed"
working-directory: cmd/pdtm/

- name: Update Run - Update All The Tools
Expand Down
49 changes: 22 additions & 27 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,28 @@ func (r *Runner) Run() error {
gologger.Verbose().Msgf("using path %s", r.options.Path)

for _, toolName := range r.options.Install {

if !path.IsSubPath(homeDir, r.options.Path) {
gologger.Error().Msgf("skipping install outside home folder: %s", toolName)
continue
}
if i, ok := utils.Contains(toolList, toolName); ok {
tool := getTool(toolName, toolList)
if err := pkg.Install(r.options.Path, toolList[i]); err != nil {
tool := toolList[i]
if tool.InstallType == types.Go && isGoInstalled() {
if err := pkg.GoInstall(r.options.Path, tool); err != nil {
gologger.Error().Msgf("%s: %s", tool.Name, err)
}
printRequirementInfo(tool)
continue
}

if err := pkg.Install(r.options.Path, tool); err != nil {
if errors.Is(err, types.ErrIsInstalled) {
gologger.Info().Msgf("%s: %s", toolName, err)
gologger.Info().Msgf("%s: %s", tool.Name, err)
} else {
gologger.Error().Msgf("error while installing %s: %s", toolName, err)
gologger.Info().Msgf("trying to install %s using go install", toolName)
if err := fallbackGoInstall(tool); err != nil {
gologger.Error().Msgf("error while installing %s using go install: %s", toolName, err)
} else {
gologger.Info().Msgf("successfully installed %s using go install", toolName)
gologger.Error().Msgf("error while installing %s: %s", tool.Name, err)
gologger.Info().Msgf("trying to install %s using go install", tool.Name)
if err := pkg.GoInstall(r.options.Path, tool); err != nil {
gologger.Error().Msgf("%s: %s", tool.Name, err)
}
}
}
Expand Down Expand Up @@ -159,16 +164,15 @@ func (r *Runner) Run() error {
return nil
}

func fallbackGoInstall(tool *types.Tool) error {
cmd := exec.Command("go", "install", "-v", fmt.Sprintf("github.com/projectdiscovery/%s/%s", tool.Name, tool.GoInstallPath))
cmd.Env = append(os.Environ(), "GOBIN="+defaultPath)
if output, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("go install failed for %s: %s", tool.Name, string(output))
func isGoInstalled() bool {
cmd := exec.Command("go", "version")
if err := cmd.Run(); err != nil {
return false
}
return nil
return true
}

func printRequirementInfo(tool *types.Tool) {
func printRequirementInfo(tool types.Tool) {
specs := getSpecs(tool)

printTitle := true
Expand Down Expand Up @@ -201,7 +205,7 @@ func getFormattedInstruction(spec types.ToolRequirementSpecification) string {
return strings.Replace(spec.Instruction, "$CMD", spec.Command, 1)
}

func getSpecs(tool *types.Tool) []types.ToolRequirementSpecification {
func getSpecs(tool types.Tool) []types.ToolRequirementSpecification {
var specs []types.ToolRequirementSpecification
for _, requirement := range tool.Requirements {
if requirement.OS == runtime.GOOS {
Expand Down Expand Up @@ -255,15 +259,6 @@ func (r *Runner) ListToolsAndEnv(tools []types.Tool) error {
// Close the runner instance
func (r *Runner) Close() {}

func getTool(toolName string, tools []types.Tool) *types.Tool {
for _, tool := range tools {
if toolName == tool.Name {
return &tool
}
}
return nil
}

func requirementSatisfied(requirementName string) bool {
if strings.HasPrefix(requirementName, "lib") {
libNames := appendLibExtensionForOS(requirementName)
Expand Down
16 changes: 16 additions & 0 deletions pkg/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
Expand Down Expand Up @@ -41,6 +42,21 @@ func Install(path string, tool types.Tool) error {
return nil
}

// GoInstall installs given tool at path
func GoInstall(path string, tool types.Tool) error {
if _, exists := ospath.GetExecutablePath(path, tool.Name); exists {
return types.ErrIsInstalled
}
gologger.Info().Msgf("installing %s with go install...", tool.Name)
cmd := exec.Command("go", "install", "-v", fmt.Sprintf("github.com/projectdiscovery/%s/%s", tool.Name, tool.GoInstallPath))
cmd.Env = append(os.Environ(), "GOBIN="+path)
if output, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("go install failed %s", string(output))
}
gologger.Info().Msgf("installed %s %s (%s)", tool.Name, tool.Version, au.BrightGreen("latest").String())
return nil
}

func install(tool types.Tool, path string) (string, error) {
builder := &strings.Builder{}
builder.WriteString(tool.Name)
Expand Down
8 changes: 8 additions & 0 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@ type Tool struct {
GoInstallPath string `json:"go_install_path" yaml:"go_install_path"`
Requirements []ToolRequirement `json:"requirements"`
Assets map[string]string `json:"assets"`
InstallType InstallType `json:"install_type" yaml:"install_type"`
}

type InstallType string

const (
Binary InstallType = "binary"
Go InstallType = "go"
)

type ToolRequirement struct {
OS string `json:"os"`
Specification []ToolRequirementSpecification `json:"specification"`
Expand Down

0 comments on commit 0aec3a0

Please sign in to comment.