Newer
Older
"forge.tedomum.net/kludge/leviathan/libs"
"forge.tedomum.net/kludge/leviathan/utils"
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.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 {
// Try to import workflow
if !runner.importWorkflow() {
utils.Logger.Error().Str("workflow", runner.Options.Scan.Flow).Msg("Unable to import workflow")
return &runner, nil
// Check modules
for _, routine := range runner.Workflow.Routines {
for _, module := range routine.Modules {
if !utils.IsYamlValid(module, runner.Options.Environment.Modules) {
return &runner, nil
// Init DSL with variables
runner.initDSL()
return &runner, 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{}) {
wg.Done()
}, ants.WithPreAlloc(true))
defer p.Release()
if !r.Options.Scan.NoClean {
utils.Logger.Info().Str("workspace", r.Workspace).Msg("Clean workspace")
CleanWorkspace(r.Workspace, r.Reports)
}
func (r *Runner) importWorkflow() bool {
fullPath := utils.CheckExistence(r.Options.Scan.Flow, r.Options.Environment.Workflows)
content, err := ParseTemplate(fullPath, r)
if err != nil {
utils.Logger.Error().Msg(err.Error())
return false
}
if err = yaml.Unmarshal(content, &r.Workflow); err != nil {
utils.Logger.Error().Msg(err.Error())
return false
}
return true
}
func (r *Runner) startModule(moduleName string) {
utils.Logger.Info().Str("module", moduleName).Msg("Run module")
// Import module before executing it
m := libs.Module{}
fullPath := utils.CheckExistence(moduleName, r.Options.Environment.Modules)
content, _ := os.ReadFile(fullPath)
if err := yaml.Unmarshal(content, &m); err != nil {
utils.Logger.Error().Msg(err.Error())
return
}
for _, report := range m.Reports {
reportPath, err := ParseString(report, r)
if err != nil {
utils.Logger.Error().Str("string", report).Msg("Unable to parse string")
}
utils.Logger.Debug().Str("module", m.Name).Str("report", reportPath).Msg("Add report to the list")
r.Reports = append(r.Reports, utils.NormalizePath(reportPath))
// 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)
}
}