Newer
Older
Target string
Workspace string
Workflow libs.Workflow
Options *libs.Options
Reports []string
DSL map[string]interface{}
func InitRunner(target string, options *libs.Options) (*Runner, error) {
runner.Options = options
runner.Workspace = path.Join(options.Environment.Workspaces, utils.CleanPath(target))
if _, err := os.Stat(runner.Workspace); os.IsNotExist(err) {
utils.Logger.Debug().Str("workspace", runner.Workspace).Msg("Create workspace folder")
if err = os.MkdirAll(runner.Workspace, 0700); err != nil {
if err := runner.readWorkflow(); err != nil {
return &runner, err
runner.initDSL()
return &runner, nil
func (r *Runner) readWorkflow() error {
// check if workflow exists
utils.Logger.Debug().Str("workflow", r.Options.Scan.Flow).Msg("Check if workflow exists")
if !WorkflowExists(r.Options.Scan.Flow, r.Options.Environment.Workflows) {
return errors.New(fmt.Sprintf("%s workflow was not found", r.Options.Scan.Flow))
}
// parse workflow
utils.Logger.Debug().Str("workflow", r.Options.Scan.Flow).Msg("Try to parse workflow")
workflow, err := WorkflowParse(r)
if err != nil {
return err
}
r.Workflow = workflow
// retrieve all modules used by the workflow
for id, routine := range workflow.Routines {
var modules []libs.Module
for _, moduleName := range routine.Modules {
utils.Logger.Debug().Str("module", moduleName).Msg("Try to parse module")
module, err := ModuleParse(moduleName, r)
if err != nil {
return err
}
modules = append(modules, module)
}
workflow.Routines[id].ModulesParsed = modules
}
return nil
}
utils.Logger.Info().
Str("runner", r.Target).
Str("workflow", r.Workflow.Name).
Msg("Start runner")
for _, routine := range r.Workflow.Routines {
var wg sync.WaitGroup
p, _ := ants.NewPoolWithFunc(r.Options.Scan.Threads*10, func(m interface{}) {
module := m.(libs.Module)
r.RunModule(module)
wg.Done()
}, ants.WithPreAlloc(true))
defer p.Release()
for _, module := range routine.ModulesParsed {
p.Invoke(module)
wg.Add(1)
}
wg.Wait()
}
if !r.Options.Scan.NoClean {
utils.Logger.Info().Str("workspace", r.Workspace).Msg("Clean workspace")
CleanWorkspace(r.Workspace, r.Reports)
}
}
func (r *Runner) RunModule(m libs.Module) {
utils.Logger.Info().Str("module", m.Name).Msg("Run module")
for _, report := range m.Reports {
utils.Logger.Debug().Str("module", m.Name).Str("report", report).Msg("Add report to the list")
r.Reports = append(r.Reports, utils.NormalizePath(report))
}
// Check if module has to be skipped
if r.Options.Scan.Resume {
skipModule := true
for _, report := range m.Reports {
if !utils.FileExists(report) {
skipModule = false
}
}
if skipModule {
utils.Logger.Info().Str("module", m.Name).Msg("skip module (--resume flag used)")
return
}
}
// Execute pre_run scripts
utils.Logger.Debug().Str("module", m.Name).Msg("Execute Pre_run scripts")
r.runScripts(m.PreRun)
}
utils.Logger.Debug().Str("module", m.Name).Msg("Execute step")
// Check requirements, skip step if requirements not met
if !r.CheckRequirements(step.Requirements) {
continue
}
// If conditions are validated
if r.CheckConditions(step.Conditions) {
// Execute commands
r.runCommands(step.Commands)
// Execute scripts
r.runScripts(step.Scripts)
} else {
// Execute commands
r.runCommands(step.RCommands)
// Execute scripts
r.runScripts(step.RScripts)
}
utils.Logger.Debug().Str("module", m.Name).Msg("Execute post_run scripts")
r.runScripts(m.PostRun)
}
}