diff --git a/test/ci-bootstrap.py b/test/ci-bootstrap.py
index 673dc5bdd1b4da072a6e3fcca1c30117827fcbbf..9a4f263dedf5b90f847415bfbc5c7b2b2ad54e1a 100755
--- a/test/ci-bootstrap.py
+++ b/test/ci-bootstrap.py
@@ -1,16 +1,20 @@
 #!/usr/bin/env python3
-#
-# Prerequisites:
-# - ansible > 2.2 (at least stretch-backports needed)
-# - ansible-runner python module
-# - python3 requests lib
-#
-# Env vars needed:
-# - COSMOS_API_TOKEN
-#
-# In Debian:
-#     apt-get install -y --no-install-recommends ansible gcc libc6-dev
-#     pip3 install ansible-runner requests
+"""
+Used by CI to bootstrap a new cluster and run tests.
+
+Prerequisites
+- ansible > 2.2 (at least stretch-backports needed)
+- ansible-runner python module
+- python3 requests lib
+
+Env vars needed:
+- COSMOS_API_TOKEN
+- CI_JOB_ID: Gitlab job ID
+
+In Debian:
+    apt-get install -y --no-install-recommends ansible gcc libc6-dev
+    pip3 install ansible-runner requests
+"""
 
 import ansible_runner
 import argparse
@@ -66,7 +70,9 @@ if __name__ == "__main__":
         # - 411: ci, ed25519
         # - 407: varac
 
+        new_name = "ci{0}".format(os.environ['CI_JOB_ID'])
         droplet = cosmos.create_droplet(
+            name=new_name,
             ssh_key_id=args.ssh_key_id,
             region='ams1',
             size=2048,
@@ -83,6 +89,7 @@ if __name__ == "__main__":
     # Get droplet ip
     droplet = cosmos.get_droplet(id)
     ip = droplet['networks']['v4'][0]['ip_address']
+    name = droplet['name']
 
     # Wait for ssh
     cosmos.wait_for_ssh(ip)
@@ -90,7 +97,13 @@ if __name__ == "__main__":
     # Create inventory
     with open('../ansible/inventory.yml.example', 'r') as stream:
         inventory = yaml.load(stream)
-    inventory['all']['hosts']['oas-dev']['ansible_host'] = ip
+    inventory['all']['hosts'][name] = inventory['all']['hosts']['oas-dev']
+    del inventory['all']['hosts']['oas-dev']
+
+    inventory['all']['hosts'][name]['ansible_host'] = ip
+    inventory['all']['children']['cluster']['hosts'] = name
+    inventory['all']['children']['master']['hosts'] = name
+    inventory['all']['children']['worker']['hosts'] = name
 
     with open('./inventory', 'w') as stream:
         yaml.dump(inventory, stream, default_flow_style=False)
@@ -101,7 +114,7 @@ if __name__ == "__main__":
         settings = yaml.load(stream)
 
     settings['ip_address'] = ip
-    settings['domain'] = 'ci.openappstack.net'
+    settings['domain'] = name + '.ci.openappstack.net'
     settings['admin_email'] = "admin@{0}".format(settings['domain'])
 
     if not os.path.exists('./env'):
@@ -109,6 +122,10 @@ if __name__ == "__main__":
     with open('./env/extravars', 'w') as stream:
         yaml.dump(settings, stream, default_flow_style=False)
 
+    if verbose:
+        print(yaml.dump(inventory, default_flow_style=False))
+        print(yaml.dump(settings, default_flow_style=False))
+
     # Bootstrap
     # playbook path here is relative to private_data_dir/project, see
     # https://ansible-runner.readthedocs.io/en/latest/intro.html#inputdir
diff --git a/test/cosmos.py b/test/cosmos.py
index 7fa670c34419049fa1a8be9291b382e631b41eaf..79ec00bf056c3f2700fe9d46428594f24e81f3c3 100755
--- a/test/cosmos.py
+++ b/test/cosmos.py
@@ -49,8 +49,8 @@ def request_api(resource: str, request_type: str = 'GET',
 
 # API calls
 
-def create_droplet(ssh_key_id: int, region: str = 'ams1', size: int = 2048,
-                   disk: int = 20, image: int = 7):
+def create_droplet(name: str, ssh_key_id: int, region: str = 'ams1',
+                   size: int = 2048, disk: int = 20, image: int = 7):
     """Create a droplet."""
     print('Creating droplet')
     name = "ci{0}".format(os.environ['CI_JOB_ID'])