blocking commands
Anastasia Macmood
anastasia.macmood at canonical.com
Fri Jan 9 06:52:36 UTC 2015
I have recently worked on blocking juju commands. If you are creating
new commands, you may find this helpful :-)
PROBLEM
Customers and stakeholders want to be able to prevent accidental damage
to their Juju deployments.
SOLUTION
To prevent running some commands, we have introduced a concept of
command block. Once the block is switched on, it has to be manually
switched off to run commands successfully.
There are currently three types of blocks developed.
DESTROY_BLOCK blocks destroy-environment command.
REMOVE_BLOCK blocks destroy-environment as well as all object removal -
machines, services, units, relations.
CHANGE_BLOCK blocks all commands from DESTROY and REMOVE blocks as well
as all environment modifications.
For more information and the list of all commands that are blocked, run
`juju help block` or `juju help unblock`.
IMPLEMENTATION
These are the steps that I followed when blocking a command.
A. Command (package cmd/juju)
1. Help for block/unblock command is updated to contain your command.
2. Delegate error processing of the client from apiserver error.
Most commonly, it would be done in the implementation of the Run from
Command interface.
E.g.
func (c *SetFluffCommand) Run(_ *cmd.Context) (err error) {
....
err := apiclient.SetFluff(args)
//there are corresponding block.BlockDestroy and block.BlockRemove
return block.ProcessBlockedError(err, block.BlockChange)
}
3. Add tests switching the block on before running the command.
Eg.
// Block operation
s.AssertConfigParameterUpdated(c, "block-all-changes", true)
B. Client (package apiserver)
1. On desired operation, before any other processing, check if the block is enabled using common.BlockChecker. Some client already have this checker embedded. To construct new checker, you'll need a state.State.
E.g.
func (c *Client) SetFluff(args params.SetFluff) error {
if err := c.check.ChangeAllowed(); err != nil {
return errors.Trace(err)
}
......
}
or
func (c *Client) SetFluff(args params.SetFluff) error {
blockChecker := common.NewBlockChecker(st)
//there are corresponding blockChecker.DestroyAllowed() and block.RemoveAllowed()
if err := blockChecker.ChangeAllowed(); err != nil {
return errors.Trace(err)
}
......
}
2. Add tests switching the block on.
C. Notify Interested Parties
At the very least, QA team might be interested in knowing that a new command became blockable. Juju documentation may need to be updated as well :)
Let me know if this information is helpful.
Sincerely Yours,
Anastasia
More information about the Juju-dev
mailing list