github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/block/unblock.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package block
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/errors"
    12  	"launchpad.net/gnuflag"
    13  
    14  	"github.com/juju/juju/cmd/modelcmd"
    15  )
    16  
    17  // NewUnblockCommand returns a new command that removes the block from
    18  // the specified operation.
    19  func NewUnblockCommand() cmd.Command {
    20  	return modelcmd.Wrap(&unblockCommand{})
    21  }
    22  
    23  // unblockCommand removes the block from desired operation.
    24  type unblockCommand struct {
    25  	modelcmd.ModelCommandBase
    26  	operation string
    27  	client    UnblockClientAPI
    28  }
    29  
    30  var (
    31  	unblockDoc = `
    32  
    33  Juju allows to safeguard deployed models from unintentional damage by preventing
    34  execution of operations that could alter model.
    35  
    36  This is done by blocking certain commands from successful execution. Blocked commands
    37  must be manually unblocked to proceed.
    38  
    39  Some commands offer a --force option that can be used to bypass a block.
    40  
    41  Commands that can be unblocked are grouped based on logical operations as follows:
    42  
    43  destroy-model includes command:
    44      destroy-model
    45  
    46  remove-object includes termination commands:
    47      destroy-model
    48      remove-machine
    49      remove-relation
    50      remove-service
    51      remove-unit
    52  
    53  all-changes includes all alteration commands
    54      add-machine
    55      add-relation
    56      add-unit
    57      authorised-keys add
    58      authorised-keys delete
    59      authorised-keys import
    60      deploy
    61      destroy-model
    62      enable-ha
    63      expose
    64      remove-machine
    65      remove-relation
    66      remove-service
    67      remove-unit
    68      resolved
    69      retry-provisioning
    70      run
    71      set
    72      set-constraints
    73      set-model-config
    74      sync-tools
    75      unexpose
    76      unset
    77      unset-model-config
    78      upgrade-charm
    79      upgrade-juju
    80      add-user
    81      change-user-password
    82      disable-user
    83      enable-user
    84  
    85  Examples:
    86     To allow the model to be destroyed:
    87     juju unblock destroy-model
    88  
    89     To allow the machines, services, units and relations to be removed:
    90     juju unblock remove-object
    91  
    92     To allow changes to the model:
    93     juju unblock all-changes
    94  
    95  See Also:
    96     juju help block
    97  `
    98  
    99  	// blockArgsFmt has formatted representation of block command valid arguments.
   100  	blockArgsFmt = fmt.Sprintf(strings.Join(blockArgs, " | "))
   101  )
   102  
   103  // assignValidOperation verifies that supplied operation is supported.
   104  func (p *unblockCommand) assignValidOperation(cmd string, args []string) error {
   105  	if len(args) < 1 {
   106  		return errors.Trace(errors.Errorf("must specify one of [%v] to %v", blockArgsFmt, cmd))
   107  	}
   108  	var err error
   109  	p.operation, err = p.obtainValidArgument(args[0])
   110  	return err
   111  }
   112  
   113  // obtainValidArgument returns polished argument:
   114  // it checks that the argument is a supported operation and
   115  // forces it into lower case for consistency.
   116  func (p *unblockCommand) obtainValidArgument(arg string) (string, error) {
   117  	for _, valid := range blockArgs {
   118  		if strings.EqualFold(valid, arg) {
   119  			return strings.ToLower(arg), nil
   120  		}
   121  	}
   122  	return "", errors.Trace(errors.Errorf("%q is not a valid argument: use one of [%v]", arg, blockArgsFmt))
   123  }
   124  
   125  // Info provides information about command.
   126  // Satisfying Command interface.
   127  func (c *unblockCommand) Info() *cmd.Info {
   128  	return &cmd.Info{
   129  		Name:    "unblock",
   130  		Args:    blockArgsFmt,
   131  		Purpose: "unblock an operation that would alter a running model",
   132  		Doc:     unblockDoc,
   133  	}
   134  }
   135  
   136  // Init initializes the command.
   137  // Satisfying Command interface.
   138  func (c *unblockCommand) Init(args []string) error {
   139  	if len(args) > 1 {
   140  		return errors.Trace(errors.New("can only specify block type"))
   141  	}
   142  
   143  	return c.assignValidOperation("unblock", args)
   144  }
   145  
   146  // SetFlags implements Command.SetFlags.
   147  func (c *unblockCommand) SetFlags(f *gnuflag.FlagSet) {
   148  	c.ModelCommandBase.SetFlags(f)
   149  }
   150  
   151  // Run unblocks previously blocked commands.
   152  // Satisfying Command interface.
   153  func (c *unblockCommand) Run(_ *cmd.Context) error {
   154  	client := c.client
   155  	if client == nil {
   156  		client, err := getBlockAPI(&c.ModelCommandBase)
   157  		if err != nil {
   158  			return errors.Trace(err)
   159  		}
   160  		defer client.Close()
   161  	}
   162  
   163  	return client.SwitchBlockOff(TypeFromOperation(c.operation))
   164  }
   165  
   166  // UnblockClientAPI defines the client API methods that unblock command uses.
   167  type UnblockClientAPI interface {
   168  	Close() error
   169  	SwitchBlockOff(blockType string) error
   170  }
   171  
   172  var getUnblockClientAPI = func(p *unblockCommand) (UnblockClientAPI, error) {
   173  	return getBlockAPI(&p.ModelCommandBase)
   174  }