Getting Started with Infrahub
If you're in the Network Automation space or attended one of the last two Autocon events, you might have come across a new tool called 'Infrahub' from OpsMill. I've been keeping an eye on it and experimenting with the product for some time now. In this blog post, we'll cover how to install Infrahub, what it is, and walk through a simple example to get you started. Let's dive in.
Infrahub Installation
Installing Infrahub is straightforward if you're familiar with Docker and have it installed. For this example, I'm using an Ubuntu 22.04 server with Docker and Docker Compose already set up. Here's all I had to do.
- Clone the Infrahub repository
- Run a single docker command to bring up the services
suresh@infrahub:~$ git clone https://github.com/opsmill/infrahub.git
Cloning into 'infrahub'...
remote: Enumerating objects: 95389, done.
remote: Counting objects: 100% (5707/5707), done.
remote: Compressing objects: 100% (2801/2801), done.
remote: Total 95389 (delta 3698), reused 4482 (delta 2877), pack-reused 89682
Receiving objects: 100% (95389/95389), 136.18 MiB | 40.26 MiB/s, done.
Resolving deltas: 100% (69451/69451), done.
suresh@infrahub:~$ cd infrahub/
suresh@infrahub:~/infrahub$ docker-compose up -d
[+] Running 70/7
✔ message-queue 10 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled
✔ task-manager 13 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled
✔ cache 8 layers [⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled
✔ infrahub-server Pulled
✔ database 5 layers [⣿⣿⣿⣿⣿] 0B/0B Pulled
✔ task-manager-db 11 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled
✔ task-worker 16 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled
[+] Running 16/16
✔ Network infrahub_default Created
✔ Volume "infrahub_storage_data" Created
✔ Volume "infrahub_workflow_data" Created
✔ Volume "infrahub_git_data" Created
✔ Volume "infrahub_git_remote_data" Created
✔ Volume "infrahub_database_data" Created
✔ Volume "infrahub_database_logs" Created
✔ Volume "infrahub_workflow_db" Created
✔ Container infrahub-database-1 Healthy
✔ Container infrahub-cache-1 Healthy
✔ Container infrahub-task-manager-db-1 Healthy
✔ Container infrahub-message-queue-1 Healthy
✔ Container infrahub-task-manager-1 Healthy
✔ Container infrahub-infrahub-server-1 Started
✔ Container infrahub-task-worker-2 Started
✔ Container infrahub-task-worker-1 Started
This command will take a few minutes to pull the necessary images and start the applications. Once everything is running, open your browser and navigate to http://<your_ip>:8000
. Use the default credentials admin
for the username and infrahub
for the password to log in.
You can also install the CLI utility called infrahubctl
on top of Infrahub. This tool will be useful as we proceed through the blog.
It's a good practice to use a virtual environment (venv
) to keep your dependencies isolated and avoid conflicts with other projects. First, create and activate a virtual environment. Once your virtual environment is activated, you can install infrahub
using the pip command.
# Create a virtual environment named 'venv'
python3 -m venv venv
# Activate the virtual environment
source venv/bin/activate
pip install 'infrahub-sdk[ctl]'
(venv) suresh@infrahub:~/infrahub$ infrahubctl version
Infrahub: v1.0.8
Python SDK: v1.1.0
Okay, How Do I Add My Device?
Once you log in, you might be wondering how to add your devices, interfaces, and inventory, but you'll notice there's no predefined place for it. This is where Infrahub differs from other tools like NetBox.
NetBox is such a mature, great product that when you log in for the first time, you have tons of tabs to manage your inventory. Infrahub, on the other hand, doesn’t come with any of that 'out of the box.'
Where Infrahub shines is in letting you manage the 'schema.' But what exactly is a 'schema'? The way I think about it is that a schema is a blueprint that defines the structure of your data. It specifies the nodes (like devices and interfaces), their attributes, and the relationships between them. This allows you to customize how you organize and manage your inventory in Infrahub.
Suppose all you want to do is add your devices and their interfaces. Well, you just need to create a simple 'schema' file and define what you want to see or manage.
Schema to Manage Devices and Interfaces
Let’s look at an example of how to create a simple schema to add a device and its interfaces. I’ll be following the official documentation for this, and I encourage you to check it out if you want to learn more.
You can load the schema into Infrahub using the infrahubctl
CLI tool we installed earlier. Before using infrahubctl
, you need to generate an API key and pass it to the CLI tool.
- Navigate to Account Settings > Token in the web GUI to create a new token.
- Once the API key is created, copy it and add it as an environment variable in your CLI.
export INFRAHUB_API_TOKEN="180f9fdb-11c5-abbd-3d6b-c51bf2bf29c6"
Schema File
As mentioned earlier, I’m using an example from the official documentation to create a schema for managing devices and their interfaces. First, you need to define the schema as a YAML file. This file can be stored anywhere, including in a Git repository for version control.
For simplicity, I’m placing the file called schema_guide.yml
in my home directory for this example.
---
version: "1.0"
nodes:
- name: Device
namespace: Network
human_friendly_id: ['hostname__value']
attributes:
- name: hostname
kind: Text
unique: true
- name: model
kind: Text
relationships:
- name: interfaces
cardinality: many
peer: NetworkInterface
kind: Component
- name: Interface
namespace: Network
attributes:
- name: name
kind: Text
- name: description
kind: Text
optional: true
relationships:
- name: device
cardinality: one
peer: NetworkDevice
optional: false
kind: Parent
Understanding the schema might seem tricky at first, but once you get the hang of it, it’s fairly straightforward to use. In this example, I’ve defined two nodes - Device and Interface and the relationship between them.
- Device Node
This node includes attributes likehostname
andmodel
. Thehostname
is marked as unique. The Device node also has a relationship with the Interface node.- Cardinality - Indicates that a device can have multiple interfaces.
- Kind - Specifies that the interface is a component of the device.
- Interface Node
The Interface node has attributes likename
and an optionaldescription
. It also has a relationship back to the Device node.- Cardinality - Indicates that an interface belongs to exactly one device.
- Kind - Specifies that the interface is a parent-child relationship with the device.
By defining this schema, you’re essentially setting up a structured way to manage devices and their interfaces within Infrahub.
human_friendly_id
for each node, which makes interacting with the API easier. For example, instead of using the ID of a device in an API call, you can simply pass its hostname. In this case, hostname__value
serves as a human-readable identifier. I plan to cover this in more detail in a future blog post with GraphQL.Let’s load this schema into Infrahub using the following command.
infrahubctl schema load ~/schema_guide.yml
schema '/home/suresh/schema_guide.yml' loaded successfully
1 schema processed in 7.981 seconds.
Now, we should be able to create a new Device and add Interfaces Infrahub as shown below.
Infrahub Branch
Before we move forward, it’s worth noting another great feature of Infrahub - it supports 'branches.' This means you can create a branch to experiment with your schema or inventory without affecting your current environment. You can merge the changes once you're happy with them into the main branch.
Let’s create a new branch called network-vendor
using the following command. Inside this branch, we will modify the schema to include a 'Vendor' field for the devices. We will also set this field as optional.
infrahubctl branch create network-vendor
Branch 'network-vendor' created successfully (180fefef-025e-3d68-c511dddca3bc).
Once the branch is created, you can view it in the web GUI under Change Control > Branches.
I'm going to update the schema to include the 'Vendor' attribute and then load this modified schema into the branch we just created.
---
version: "1.0"
nodes:
- name: Device
namespace: Network
human_friendly_id: ['hostname__value']
attributes:
- name: hostname
kind: Text
unique: true
- name: model
kind: Text
- name: vendor
kind: Text
optional: true
relationships:
- name: interfaces
cardinality: many
peer: NetworkInterface
kind: Component
- name: Interface
namespace: Network
attributes:
- name: name
kind: Text
- name: description
kind: Text
optional: true
relationships:
- name: device
cardinality: one
peer: NetworkDevice
optional: false
kind: Parent
infrahubctl schema load --branch network-vendor ~/schema_guide.yml
schema '/home/suresh/schema_guide.yml' loaded successfully
1 schema processed in 9.764 seconds.
While we are inside the new branch, you can check if everything looks as good as expected and if you are happy with the changes, you can merge the branch to the main branch.
You can also create a new branch via the web GUI. Let's create a new branch and modify an existing device.
For the sake of simplicity, I'm going to modify an existing device under this new branch to include the vendor name as shown below.
Once we make the changes, we can view the diff right from the GUI to see what has changed.
Schema Library
If you are thinking 'Oh, do I need to now go and create my own schema', hold your thought because there are plenty of schemas readily available from Opsmill's GitHub repo. Feel free to check it out but here is an example of importing the base schema and some extensions from the library.
git clone https://github.com/opsmill/schema-library.git
Cloning into 'schema-library'...
remote: Enumerating objects: 1173, done.
remote: Counting objects: 100% (483/483), done.
remote: Compressing objects: 100% (328/328), done.
remote: Total 1173 (delta 210), reused 322 (delta 155), pack-reused 690 (from 1)
Receiving objects: 100% (1173/1173), 288.38 KiB | 3.95 MiB/s, done.
Resolving deltas: 100% (558/558), done.
infrahubctl schema load --branch base-schema /home/suresh/schema-library/base
infrahubctl schema load --branch base-schema /home/suresh/schema-library/extensions/vlan/
infrahubctl schema load --branch base-schema /home/suresh/schema-library/extensions/location_minimal/
Here you can see there are plenty of attributes for 'Network Device' like status, device type, platform, serial, location and more.
Closing Thoughts
I hope this gives you an idea of what Infrahub is and the problems it aims to solve. I’m still new to Infrahub and learning as I go. In the comments, let me know what you think about this approach and whether you’d prefer to manage your own schema. I’m planning to write more content on Infrahub, so don’t forget to subscribe.