зеркало из https://github.com/mozilla/mig.git
[minor] move common client functions to mig/client
This commit is contained in:
Родитель
46a62a107c
Коммит
abed1dce2f
|
@ -570,3 +570,170 @@ func (cli Client) EvaluateAgentTarget(target string) (agents []mig.Agent, err er
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FollowAction continuously loops over an action and prints its completion status in os.Stderr.
|
||||
// when the action reaches its expiration date, FollowAction prints its final status and returns.
|
||||
func (cli Client) FollowAction(a mig.Action) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("followAction() -> %v", e)
|
||||
}
|
||||
}()
|
||||
fmt.Fprintf(os.Stderr, "Following action ID %.0f. ", a.ID)
|
||||
sent := 0
|
||||
dotter := 0
|
||||
previousctr := 0
|
||||
status := ""
|
||||
attempts := 0
|
||||
var completion float64
|
||||
for {
|
||||
a, _, err = cli.GetAction(a.ID)
|
||||
if err != nil {
|
||||
attempts++
|
||||
time.Sleep(1 * time.Second)
|
||||
if attempts >= 30 {
|
||||
panic("failed to retrieve action after 30 seconds. launch may have failed")
|
||||
}
|
||||
continue
|
||||
}
|
||||
if status == "" {
|
||||
status = a.Status
|
||||
}
|
||||
if status != a.Status {
|
||||
fmt.Fprintf(os.Stderr, "status=%s\n", a.Status)
|
||||
status = a.Status
|
||||
}
|
||||
// exit follower mode if status isn't one we follow,
|
||||
// or enough commands have returned
|
||||
// or expiration time has passed
|
||||
if (status != "init" && status != "preparing" && status != "inflight") ||
|
||||
(a.Counters.Done > 0 && a.Counters.Done >= a.Counters.Sent) ||
|
||||
(time.Now().After(a.ExpireAfter)) {
|
||||
goto finish
|
||||
break
|
||||
}
|
||||
// init counters
|
||||
if sent == 0 {
|
||||
if a.Counters.Sent == 0 {
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
} else {
|
||||
sent = a.Counters.Sent
|
||||
}
|
||||
}
|
||||
if a.Counters.Done > 0 && a.Counters.Done > previousctr {
|
||||
completion = (float64(a.Counters.Done) / float64(a.Counters.Sent)) * 100
|
||||
if completion > 99.9 && a.Counters.Done != a.Counters.Sent {
|
||||
completion = 99.9
|
||||
}
|
||||
previousctr = a.Counters.Done
|
||||
fmt.Fprintf(os.Stderr, "%.0f%% ", completion)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, ".")
|
||||
time.Sleep(2 * time.Second)
|
||||
dotter++
|
||||
}
|
||||
finish:
|
||||
fmt.Fprintf(os.Stderr, "done in %s\n", time.Now().Sub(a.StartTime).String())
|
||||
a.PrintCounters()
|
||||
return
|
||||
}
|
||||
|
||||
func (cli Client) PrintActionResults(a mig.Action, show string) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("PrintActionResults() -> %v", e)
|
||||
}
|
||||
}()
|
||||
found := false
|
||||
var resource *cljs.Resource
|
||||
switch show {
|
||||
case "found":
|
||||
found = true
|
||||
target := fmt.Sprintf("search?type=command&limit=1000000&foundanything=true&actionid=%.0f", a.ID)
|
||||
resource, err = cli.GetAPIResource(target)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
case "notfound":
|
||||
target := fmt.Sprintf("search?type=command&limit=1000000&foundanything=false&actionid=%.0f", a.ID)
|
||||
resource, err = cli.GetAPIResource(target)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
case "all":
|
||||
target := fmt.Sprintf("search?type=command&limit=1000000&actionid=%.0f", a.ID)
|
||||
resource, err = cli.GetAPIResource(target)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid parameter '%s'", show)
|
||||
}
|
||||
count := 0
|
||||
for _, item := range resource.Collection.Items {
|
||||
for _, data := range item.Data {
|
||||
if data.Name != "command" {
|
||||
continue
|
||||
}
|
||||
cmd, err := ValueToCommand(data.Value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = PrintCommandResults(cmd, found, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
count++
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "%d agents have %s results\n", count, show)
|
||||
return
|
||||
}
|
||||
|
||||
func PrintCommandResults(cmd mig.Command, found, showAgent bool) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("PrintCommandResults() -> %v", e)
|
||||
}
|
||||
}()
|
||||
for i, result := range cmd.Results {
|
||||
buf, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(cmd.Action.Operations) <= i {
|
||||
fmt.Fprintf(os.Stderr, "[error] no operation maps results %d\n", i)
|
||||
for _, rerr := range result.Errors {
|
||||
fmt.Fprintf(os.Stderr, "[error] %s\n", rerr)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// verify that we know the module
|
||||
moduleName := cmd.Action.Operations[i].Module
|
||||
if _, ok := mig.AvailableModules[moduleName]; !ok {
|
||||
fmt.Fprintf(os.Stderr, "Skipping unknown module '%s'\n", moduleName)
|
||||
continue
|
||||
}
|
||||
modRunner := mig.AvailableModules[moduleName]()
|
||||
// look for a result printer in the module
|
||||
if _, ok := modRunner.(mig.HasResultsPrinter); ok {
|
||||
results, err := modRunner.(mig.HasResultsPrinter).PrintResults(buf, found)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, res := range results {
|
||||
if showAgent {
|
||||
agtname := cmd.Agent.Name
|
||||
fmt.Printf("%s %s\n", agtname, res)
|
||||
} else {
|
||||
fmt.Println(res)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "no printer available for module '%s'\n", moduleName)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "command status: %s\n", cmd.Status)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ times show the various timestamps of the action
|
|||
fmt.Printf("Action '%s' successfully launched with ID '%.0f' on target '%s'\n",
|
||||
a.Name, a.ID, a.Target)
|
||||
if follow {
|
||||
err = followAction(a, cli)
|
||||
err = cli.FollowAction(a)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -143,7 +143,16 @@ times show the various timestamps of the action
|
|||
}
|
||||
fmt.Println("Reload succeeded")
|
||||
case "results":
|
||||
err = actionPrintResults(a, links, orders, cli)
|
||||
show := "all"
|
||||
if len(orders) > 1 {
|
||||
switch orders[1] {
|
||||
case "found":
|
||||
show = "found"
|
||||
case "notfound":
|
||||
show = "notfound"
|
||||
}
|
||||
}
|
||||
err = cli.PrintActionResults(a, show)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -330,65 +339,3 @@ func actionPrintLinks(links []cljs.Link, orders []string) (err error) {
|
|||
fmt.Printf(" found\n")
|
||||
return
|
||||
}
|
||||
|
||||
func actionPrintResults(a mig.Action, links []cljs.Link, orders []string, cli client.Client) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("actionPrintResuls() -> %v", e)
|
||||
}
|
||||
}()
|
||||
found := false
|
||||
if len(orders) > 1 {
|
||||
if orders[1] == "found" {
|
||||
found = true
|
||||
} else {
|
||||
fmt.Printf("Unknown option '%s'\n", orders[1])
|
||||
}
|
||||
}
|
||||
if found {
|
||||
// if we want foundes, use the search api, it's faster than
|
||||
// iterating through each link when we have thousands of them
|
||||
target := "search?type=command&limit=1000000&foundanything=true"
|
||||
target += "&actionid=" + fmt.Sprintf("%.0f", a.ID)
|
||||
resource, err := cli.GetAPIResource(target)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, item := range resource.Collection.Items {
|
||||
for _, data := range item.Data {
|
||||
if data.Name != "command" {
|
||||
continue
|
||||
}
|
||||
cmd, err := client.ValueToCommand(data.Value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = commandPrintResults(cmd, true, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, link := range links {
|
||||
// TODO: replace the url parsing hack with proper link creation in API response
|
||||
id := strings.Split(link.Href, "=")[1]
|
||||
cmdid, err := strconv.ParseFloat(id, 64)
|
||||
if err != nil {
|
||||
fmt.Println("ERROR: invalid command id in link:", link)
|
||||
continue
|
||||
}
|
||||
cmd, err := cli.GetCommand(cmdid)
|
||||
if err != nil {
|
||||
fmt.Println("ERROR: failed to get command id", cmdid)
|
||||
continue
|
||||
}
|
||||
err = commandPrintResults(cmd, found, true)
|
||||
if err != nil {
|
||||
fmt.Println("ERROR: failed to print results from command id", cmdid)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"fmt"
|
||||
"github.com/bobappleyard/readline"
|
||||
"io"
|
||||
"mig"
|
||||
"mig/client"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -101,7 +100,7 @@ results <found> print the results. if "found" is set, only print results that ha
|
|||
fmt.Printf("Unknown option '%s'\n", orders[1])
|
||||
}
|
||||
}
|
||||
err = commandPrintResults(cmd, found, false)
|
||||
err = client.PrintCommandResults(cmd, found, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -117,48 +116,6 @@ exit:
|
|||
return
|
||||
}
|
||||
|
||||
func commandPrintResults(cmd mig.Command, found, showAgent bool) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("commandPrintResults() -> %v", e)
|
||||
}
|
||||
}()
|
||||
for i, result := range cmd.Results {
|
||||
buf, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// verify that we know the module
|
||||
moduleName := cmd.Action.Operations[i].Module
|
||||
if _, ok := mig.AvailableModules[moduleName]; !ok {
|
||||
fmt.Println("Skipping unknown module", moduleName)
|
||||
continue
|
||||
}
|
||||
modRunner := mig.AvailableModules[moduleName]()
|
||||
// look for a result printer in the module
|
||||
if _, ok := modRunner.(mig.HasResultsPrinter); ok {
|
||||
results, err := modRunner.(mig.HasResultsPrinter).PrintResults(buf, found)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, res := range results {
|
||||
if showAgent {
|
||||
agtname := cmd.Agent.Name
|
||||
if useShortNames {
|
||||
agtname = shorten(agtname)
|
||||
}
|
||||
fmt.Printf("%s %s\n", agtname, res)
|
||||
} else {
|
||||
fmt.Println(res)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("no result printer available for module '%s'. try `json pretty`\n", moduleName)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func commandPrintShort(data interface{}) (idstr, agtname, duration, status string, err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
|
|
Загрузка…
Ссылка в новой задаче