The node object

TODO: examples and documentation.

from deployer.node import SimpleNode

class SayHello(SimpleNode):
    def hello(self):
        self.host.run('echo hello world')

Note

It is interesting to know that self is actually not a Node instance, but an Env object which will proxy this actual Node class. This is because there is some metaclass magic going on, which takes care of sandboxing, logging and some other nice stuff, that you get for free.

Except that a few other variables like self.console are available, you normally won’t notice anything.

Running the code

from deployer.node import Env

env = Env(MyNode())
env.hello()

Inheritance

A node is meant to be reusable. It is encouraged to inherit from such a node class and overwrite properties or class members.

Expansion of double underscores

TODO: ...

The difference between Node and SimpleNode

TODO: ...

.Array and .JustOne

TODO: ...

Using contrib.nodes

The deployer framework is delivered with a contrib.nodes directory which contains nodes that should be generic enough to be usable by a lot of people. Even if you can’t use them in your case, they may be good examples of how to do certain things. So don’t be afraid to look at the source code, you can learn some good practices there. Take these and inherit as you want to, or start from scratch if you prefer that way.

Some recommended contrib nodes:

  • deployer.contrib.nodes.config.Config

    This a the base class that we are using for every configuration file. It is very useful for when you are automatically generating server configurations according to specific deployment configurations. Without any efford, this class will allow you to do diff’s between your new, generated config, and the config that’s currently on the server side.

Reference

class deployer.node.Env(node, pty=None, logger=None, is_sandbox=False)

Wraps a Node into a context where actions can be executed.

Instead of self, the first parameter of a Node-action will be this instance. It acts like a proxy to the Node, but in the meantime it takes care of logging, sandboxing, the terminal and context.

console

Interface for user input. Returns a deployer.console.Console instance.

hosts

deployer.host_container.HostsContainer instance. This is the proxy to the actual hosts.

initialize_node(node_class)

Dynamically initialize a node from within another node. This will make sure that the node class is initialized with the correct logger, sandbox and pty settings. e.g:

Parameters:node_class – A Node subclass.
class SomeNode(Node):
    def action(self):
        pass

class RootNode(Node):
    def action(self):
        # Wrap SomeNode into an Env object
        node = self.initialize_node(SomeNode)

        # Use the node.
        node.action2()
class deployer.node.Node(parent=None)

This is the base class for any deployment node.

class deployer.node.SimpleNode(parent=None)

A SimpleNode is a Node which has only one role, named host. Multiple hosts can be given for this role, but all of them will be isolated, during execution. This allows parallel executing of functions on each ‘cell’.

deployer.node.suppress_action_result(action)

When using a deployment shell, don’t print the returned result to stdout. For example, when the result is superfluous to be printed, because the action itself contains already print statements, while the result can be useful for the caller.

deployer.node.dont_isolate_yet(func)

If the node has not yet been separated in serveral parallel, isolated nodes per host. Don’t do it yet for this function. When anothor action of the same host without this decorator is called, the node will be split.

It’s for instance useful for reading input, which is similar for all isolated executions, (like asking which Git Checkout has to be taken), before forking all the threads.

Note that this will not guarantee that a node will not be split into its isolations, it does only say, that it does not have to. It is was already been split before, and this is called from a certain isolation, we’ll keep it like that.

deployer.node.alias(name)

Give this node action an alias. It will also be accessable using that name in the deployment shell. This is useful, when you want to have special characters which are not allowed in Python function names, like dots, in the name of an action.