// For mig.RunnerResult r, get the results associated with this job from the // API. func getResults(r mig.RunnerResult) (err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("getResults() -> %v", e) } }() mlog("fetching results for %v/%.0f", r.EntityName, r.Action.ID) cli, err := client.NewClient(ctx.ClientConf, "mig-runner-results") if err != nil { panic(err) } results, err := cli.FetchActionResults(r.Action) if err != nil { panic(err) } mlog("%v/%.0f: fetched results, %v commands returned", r.EntityName, r.Action.ID, len(results)) // Store the results outpath, err := getResultsStoragePath(r.EntityName) if err != nil { panic(err) } outpath = path.Join(outpath, fmt.Sprintf("%.0f.json", r.Action.ID)) fd, err := os.Create(outpath) if err != nil { panic(err) } defer fd.Close() r.Commands = results buf, err := json.Marshal(r) if err != nil { panic(err) } _, err = fd.Write(buf) if err != nil { panic(err) } mlog("wrote results for %.0f to %v", r.Action.ID, outpath) // If a plugin has been configured on the result set, call the // plugin on the data. if r.UsePlugin != "" { err = runPlugin(r) if err != nil { panic(err) } } else { mlog("no output plugin for %.0f, skipping plugin processing", r.Action.ID) } return nil }
// Launch an action represented by a scheduler entity, this function takes // care of submitting the action to the API and making a note of when to // attempt to retrieve the results of the action. func (e *entity) launchAction() (err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("launchAction() -> %v", e) } }() // Load the action from the entity run directory actpath := path.Join(e.baseDir, "action.json") act, err := mig.ActionFromFile(actpath) if err != nil { panic(err) } act.Name = fmt.Sprintf("mig-runner: %v", e.name) cli, err := client.NewClient(ctx.ClientConf, "mig-runner") if err != nil { panic(err) } // Borrow some logic from the action generator. Set a validation // period starting in the past so our action starts immediately. window := time.Duration(-60 * time.Second) act.ValidFrom = time.Now().Add(window).UTC() exstring := defaultExpiry if e.cfg.Configuration.Expiry != "" { exstring = e.cfg.Configuration.Expiry } period, err := time.ParseDuration(exstring) if err != nil { panic(err) } // Add the window period to the desired expiry since our start // time begins in the past. period += -window act.ExpireAfter = act.ValidFrom.Add(period) act, err = cli.CompressAction(act) if err != nil { panic(err) } asig, err := cli.SignAction(act) if err != nil { panic(err) } act = asig res, err := cli.PostAction(act) if err != nil { panic(err) } mlog("%v: launched action %.0f", e.name, res.ID) // If we only dispatch this action we are done here. if e.cfg.Configuration.SendOnly { return nil } // Notify the results processor an action is in-flight re := mig.RunnerResult{} re.EntityName = e.name re.Action = res re.UsePlugin = e.cfg.Configuration.Plugin ctx.Channels.Results <- re return nil }