github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/application/resolved.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package application 5 6 import ( 7 "fmt" 8 9 "github.com/juju/cmd" 10 "github.com/juju/errors" 11 "github.com/juju/gnuflag" 12 "gopkg.in/juju/names.v2" 13 14 "github.com/juju/juju/api/application" 15 jujucmd "github.com/juju/juju/cmd" 16 "github.com/juju/juju/cmd/juju/block" 17 "github.com/juju/juju/cmd/modelcmd" 18 ) 19 20 func NewResolvedCommand() cmd.Command { 21 return modelcmd.Wrap(&resolvedCommand{}) 22 } 23 24 // resolvedCommand marks a unit in an error state as ready to continue. 25 type resolvedCommand struct { 26 modelcmd.ModelCommandBase 27 applicationResolveAPI applicationResolveAPI 28 clientAPI clientAPI 29 30 UnitNames []string 31 NoRetry bool 32 All bool 33 } 34 35 func (c *resolvedCommand) Info() *cmd.Info { 36 return jujucmd.Info(&cmd.Info{ 37 Name: "resolved", 38 Args: "[<unit> ...]", 39 Purpose: "Marks unit errors resolved and re-executes failed hooks.", 40 Aliases: []string{"resolve"}, 41 }) 42 } 43 44 func (c *resolvedCommand) SetFlags(f *gnuflag.FlagSet) { 45 c.ModelCommandBase.SetFlags(f) 46 f.BoolVar(&c.NoRetry, "no-retry", false, "Do not re-execute failed hooks on the unit") 47 f.BoolVar(&c.All, "all", false, "Marks all units in error as resolved") 48 } 49 50 func (c *resolvedCommand) Init(args []string) error { 51 if c.All { 52 if len(args) > 0 { 53 return errors.NotSupportedf("specifying unit names(s) with --all") 54 } 55 return nil 56 } 57 if len(args) > 0 { 58 c.UnitNames = args 59 for _, u := range args { 60 if !names.IsValidUnit(u) { 61 return errors.NotValidf("unit name %q", u) 62 } 63 } 64 } else { 65 return errors.Errorf("no unit specified") 66 } 67 return nil 68 } 69 70 type applicationResolveAPI interface { 71 Close() error 72 BestAPIVersion() int 73 ResolveUnitErrors(units []string, all, retry bool) error 74 } 75 76 type clientAPI interface { 77 Resolved(unit string, retry bool) error 78 Close() error 79 } 80 81 func (c *resolvedCommand) getapplicationResolveAPI() (applicationResolveAPI, error) { 82 if c.applicationResolveAPI != nil { 83 return c.applicationResolveAPI, nil 84 } 85 86 root, err := c.NewAPIRoot() 87 if err != nil { 88 return nil, errors.Trace(err) 89 } 90 return application.NewClient(root), nil 91 } 92 93 func (c *resolvedCommand) getClientAPI() (clientAPI, error) { 94 if c.clientAPI != nil { 95 return c.clientAPI, nil 96 } 97 return c.NewAPIClient() 98 } 99 100 func (c *resolvedCommand) Run(ctx *cmd.Context) error { 101 applicationResolveAPI, err := c.getapplicationResolveAPI() 102 if err != nil { 103 return errors.Trace(err) 104 } 105 defer applicationResolveAPI.Close() 106 107 if applicationResolveAPI.BestAPIVersion() >= 6 { 108 return block.ProcessBlockedError(applicationResolveAPI.ResolveUnitErrors(c.UnitNames, c.All, !c.NoRetry), block.BlockChange) 109 } 110 111 if c.All { 112 return errors.Errorf("resolving all units or more than one unit not support by this version of Juju") 113 } 114 115 clientAPI, err := c.getClientAPI() 116 if err != nil { 117 return errors.Trace(err) 118 } 119 defer clientAPI.Close() 120 for _, unit := range c.UnitNames { 121 if len(c.UnitNames) > 1 { 122 fmt.Fprintf(ctx.GetStdout(), "resolving unit %q\n", unit) 123 } 124 if err := block.ProcessBlockedError(clientAPI.Resolved(unit, !c.NoRetry), block.BlockChange); err != nil { 125 return errors.Annotatef(err, "error resolving unit %q", unit) 126 } 127 } 128 if len(c.UnitNames) > 1 { 129 fmt.Fprintln(ctx.GetStdout(), "all units resolved") 130 } 131 return nil 132 }