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