github.com/technosophos/deis@v1.7.1-0.20150915173815-f9005256004b/deisctl/backend/fleet/stop.go (about) 1 package fleet 2 3 import ( 4 "fmt" 5 "io" 6 "sync" 7 "time" 8 9 "github.com/coreos/fleet/schema" 10 "github.com/deis/deis/pkg/prettyprint" 11 ) 12 13 var stateFmt = prettyprint.Colorize("{{.Yellow}}%v:{{.Default}} %v/%v") 14 15 // Stop units and wait for their desiredState 16 func (c *FleetClient) Stop(targets []string, wg *sync.WaitGroup, out, ew io.Writer) { 17 // expand @* targets 18 expandedTargets, err := c.expandTargets(targets) 19 if err != nil { 20 fmt.Fprintln(ew, err.Error()) 21 return 22 } 23 24 for _, target := range expandedTargets { 25 wg.Add(1) 26 go doStop(c, target, wg, out, ew) 27 } 28 return 29 } 30 31 func doStop(c *FleetClient, target string, wg *sync.WaitGroup, out, ew io.Writer) { 32 defer wg.Done() 33 34 // prepare string representation 35 component, num, err := splitTarget(target) 36 if err != nil { 37 fmt.Fprintln(ew, err.Error()) 38 return 39 } 40 name, err := formatUnitName(component, num) 41 if err != nil { 42 fmt.Fprintln(ew, err.Error()) 43 return 44 } 45 46 requestState := "loaded" 47 desiredState := "dead" 48 49 if err := c.Fleet.SetUnitTargetState(name, requestState); err != nil { 50 fmt.Fprintln(ew, err.Error()) 51 return 52 } 53 54 // start with the likely subState to avoid sending it across the channel 55 lastSubState := "running" 56 57 for { 58 // poll for unit states 59 states, err := c.Fleet.UnitStates() 60 if err != nil { 61 fmt.Fprintln(ew, err.Error()) 62 return 63 } 64 65 // FIXME: fleet UnitStates API forces us to iterate for now 66 var currentState *schema.UnitState 67 for _, s := range states { 68 if name == s.Name { 69 currentState = s 70 break 71 } 72 } 73 if currentState == nil { 74 fmt.Fprintf(ew, "Could not find unit: %v\n", name) 75 return 76 } 77 78 // if subState changed, send it across the output channel 79 if lastSubState != currentState.SystemdSubState { 80 l := prettyprint.Overwritef(stateFmt, name, currentState.SystemdActiveState, currentState.SystemdSubState) 81 fmt.Fprintf(out, l) 82 } 83 84 // break when desired state is reached 85 if currentState.SystemdSubState == desiredState { 86 fmt.Fprintln(out) 87 return 88 } 89 90 lastSubState = currentState.SystemdSubState 91 92 if lastSubState == "failed" { 93 o := prettyprint.Colorize("{{.Red}}The service '%s' failed while stopping.{{.Default}}\n") 94 fmt.Fprintf(ew, o, target) 95 return 96 } 97 98 time.Sleep(250 * time.Millisecond) 99 } 100 }