Quickstart

This is the 10 minute intro into BundleWrap. Fasten your seatbelt.

Installation

First, open a terminal and install BundleWrap:

pip install bundlewrap

Create a repository

Now you'll need to create your repository:

mkdir my_bundlewrap_repo
cd my_bundlewrap_repo
bw repo create

You will note that some files have been created. Let's check them out:

cat nodes.py
cat groups.py

The contents should be fairly self-explanatory, but you can always check the docs on these files if you want to go deeper.

It is highly recommended to use git or a similar tool to keep track of your repository. You may want to start doing that right away.

At this point you will want to edit nodes.py and maybe change "localhost" to the hostname of a system you have passwordless (including sudo) SSH access to.

BundleWrap will honor your ~/.ssh/config, so if ssh mynode.example.com sudo id works without any password prompts in your terminal, you're good to go.

If you want to keep working on "localhost", then the above still applies in that ssh localhost sudo id needs to work without any password prompts. Verify that:

  1. an SSH daemon is listening on 127.0.0.1
  2. a relevant public key is in the ~/.ssh/authorized_keys file
  3. the ~/.ssh/authorized_keys file is not world-writable
  4. your user or group has ALL=(ALL) NOPASSWD: ALL set in the /etc/sudoers file

Run a command

The first thing you can do is run a command on your army of one node:

bw -a run node-1 "uptime"
The -a switch tells bw to automatically trust unknown SSH host keys (when you're connecting to a new node). By default, only known host keys will be accepted.

You should see something like this:

› node-1   20:16:26 up 34 days,  4:10,  0 users,  load average: 0.00, 0.01, 0.05
✓ node-1  completed after 0.366s

Instead of a node name ("node-1" in this case) you can also use a group name (such as "all") from your groups.py.

Create a bundle

BundleWrap stores node configuration in bundles. A bundle is a collection of items such as files, system packages or users. To create your first bundle, type:

bw repo bundle create mybundle

Now that you have created your bundle, it's important to tell BundleWrap which nodes will have this bundle. You can assign bundles to nodes using either groups.py or nodes.py, here we'll use the latter:

nodes = {
    'node-1': {
        'bundles': (
            "mybundle",
        ),
        'hostname': "mynode-1.local",
    },
}

Create a file template

To manage a file, you need two things:

  1. a file item in your bundle
  2. a template for the file contents

Add this to your bundles/mybundle/items.py:

files = {
    '/etc/motd': {
        'content_type': 'mako',  # use the Mako template engine for this file
        'source': "mymotd",  # filename of the template
    },
}

Then write the file template:

vim bundles/mybundle/files/mymotd

You can use this for example content:

Welcome to ${node.name}!

Note that the source attribute in items.py contains a path relative to the files directory of your bundle.

Apply configuration

Now all that's left is to run bw apply:

bw apply -i node-1

BundleWrap will ask to replace your previous MOTD:

i node-1  started at 2016-02-13 21:25:45
? node-1
? node-1  ╭─ file:/etc/motd
? node-1  │
? node-1  │  content
? node-1  │  --- <node>
? node-1  │  +++ <bundlewrap>
? node-1  │  @@ -1 +1 @@
? node-1  │  -your old motd
? node-1  │  +Welcome to node-1!
? node-1  │
? node-1  ╰─ Fix file:/etc/motd? [Y/n]

That completes the quickstart tutorial!

Further reading

Here are some suggestions on what to do next:

Have fun! If you have any questions, feel free to drop by on IRC or GitHub.