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  }