cli/cmd/wait.go

105 lines
2.1 KiB
Go

package cmd
import (
"fmt"
"strings"
"time"
ntypes "github.com/rancher/norman/types"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var (
waitTypes = []string{"cluster", "project"}
)
func WaitCommand() cli.Command {
return cli.Command{
Name: "wait",
Usage: "Wait for resources " + strings.Join(waitTypes, ", "),
ArgsUsage: "[ID/NAME]",
Action: defaultAction(wait),
Flags: []cli.Flag{
cli.IntFlag{
Name: "timeout",
Usage: "Time in seconds to wait for a resource",
Value: 120,
},
},
}
}
func wait(ctx *cli.Context) error {
if ctx.NArg() == 0 {
return cli.ShowCommandHelp(ctx, "wait")
}
c, err := GetClient(ctx)
if err != nil {
return err
}
resource, err := Lookup(c, ctx.Args().First(), waitTypes...)
if err != nil {
return err
}
mapResource := map[string]interface{}{}
// Initial check shortcut
err = c.ByID(resource, &mapResource)
if err != nil {
return err
}
ok, err := checkDone(resource, mapResource)
if err != nil {
return err
}
if ok {
return nil
}
timeout := time.After(time.Duration(ctx.Int("timeout")) * time.Second)
ticker := time.NewTicker(time.Second)
for {
select {
case <-timeout:
return fmt.Errorf("Timeout reached %v:%v transitioningMessage: %v", resource.Type, resource.ID, mapResource["transitioningMessage"])
case <-ticker.C:
err = c.ByID(resource, &mapResource)
if err != nil {
return err
}
ok, err := checkDone(resource, mapResource)
if err != nil {
return err
}
if ok {
return nil
}
}
}
}
func checkDone(resource *ntypes.Resource, data map[string]interface{}) (bool, error) {
transitioning := fmt.Sprint(data["transitioning"])
logrus.Debugf("%s:%s transitioning=%s state=%v", resource.Type, resource.ID, transitioning,
data["state"])
switch transitioning {
case "yes":
return false, nil
case "error":
if data["state"] == "provisioning" {
break
}
return false, fmt.Errorf("%v:%v failed, transitioningMessage: %v", resource.Type, resource.ID, data["transitioningMessage"])
}
return data["state"] == "active", nil
}