Usage¶
We will show how to use the client and the CLI by performing the same operations with both. This tutorial is mainly inspired by the wapidoc tutorial.
Instantiate a client¶
To instantiate a new client you will need to perform the following command:
from infoblox import Client
client = Client(url='https://foo.com/wapi/v2.8', user='foo', password='foo')
Note
You can define three environment variables IB_URL
, IB_USER
and IB_PASSWORD
and later instantiate the client
without using keyword parameters like this client = Client()
Note
If you have a .env
file with configured environment variables, you can instantiate the client as follows:
client = Client(dot_env_path=path_to_env_file)
Note
If you have configured a client certificate, you can pass the path of the .pem
file or a tuple
(certificate_file, private_key)
to the cert
keyword argument of the Client
class like this:
client = Client(cert=path_to_pem_file)
or client = Client(cert=(path_to_certificate_file, path_to_private_key))
Configure the CLI¶
The CLI included with the project is called ib
. To use it, you will have to configure the following environment
variables:
- IB_USER: the user to connect to
- IB_PASSWORD: the user's password
- IB_URL: the wapi url which must be of the form
https://foo.com/wapi/v2.X
To not repeat yourself every time you need to use the CLI, you can create a .env
file with the above environment
variables and put it in your working directory. ib
command will automatically load this file so you can focus on
performing tasks.
Note
you can activate shell completion by performing the command ib shell-completion
. This will only work on bash
,
fish
, zsh
and PowerShell
To know more about configuring the CLI, you can check the CLI page.
Performing actions¶
Create a network¶
Using the client:
network = client.get_object('network')
network.create(network='10.1.0.0/16')
Using the CLI:
ib object -n network create -a '{"network":"10.1.0.0/16"}'
N.B: On PowerShell you will need to use a different syntax to encode properly json string. In the rest of the tutorial, we will use the bash-like syntax.
ib object -n network create -a "{\"network\":\"10.1.0.0/16\"}"
Note
To know all options and sub-commands available within a command, you can use the -h
option.
The response will contain the reference of the created network:
"network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0%2F16"
Read a network¶
Using the client:
network.get()
using the CLI:
ib object -n network get
You will get an output similar to this:
[
{
"_ref": "network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0%2F16",
"network": "10.1.0.0/16",
"network_view": "default"
},
{
"_ref": "network/ZG5zLm5ldHdvcmskMTAuMi4wLjAvMTYvMA:10.2.0.0%2F16",
"network": "10.2.0.0/16",
"network_view": "default"
}
]
Note
All responses are returned in json
format, there is no xml
supported
Modify a network¶
Using the client:
network.update(object_ref='network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0/16', comment='just a comment')
using the CLI:
ib object -n network update -o network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0%2F16 -a '{"comment":"just a comment"}'
The response will contain the reference of the modified network. This could be different from the created one.
"network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0%2F16"
To check if the network was modified, we will search it. Note the usage of return_fields
parameter to specify which
fields to return.
Using the client:
network.get(return_fields=['network', 'networkview', 'comment'])
using the CLI:
ib object -n network get --return-fields=network,networkview,comment
Note that the 10.1.0.0/16 network has been modified:
[
{
"_ref": "network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0%2F16",
"comment": "just a comment",
"network": "10.1.0.0/16",
"network_view": "default"
},
{
"_ref": "network/ZG5zLm5ldHdvcmskMTAuMi4wLjAvMTYvMA:10.2.0.0%2F16",
"network": "10.2.0.0/16",
"network_view": "default"
}
]
Search for a network¶
To search for networks with comments that contain the word just in a case-insensitive way, we can perform the following operations.
Using the client:
network.get(params={'comment~:': 'just'})
using the CLI:
ib object -n network get -p '{"comment~:":"just"}'
You will have an empty list in response if there is no matching or a response similar to this:
[
{
"_ref": "network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0%2F16",
"comment": "just a comment",
"network": "10.1.0.0/16",
"network_view": "default"
}
]
Delete a network¶
Using the client:
network.delete(object_ref='network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0/16')
using the CLI:
ib object -n network delete -o network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0%2F16
The reference of the deleted network will be returned:
"network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0%2F16"
Create a host record¶
To create a host record, we will first need to create a zone.
using the client:
zone_auth = client.get_object('zone_auth')
zone_auth.create(fqdn='zone.com')
using the CLI:
ib object -n zone_auth create -a '{"fqdn":"zone.com"}'
Then now we can create a host.
using the client:
record_host = client.get_object('record:host')
record_host.create(ipv4addrs=[{'ipv4addr':'10.222.0.12'}], name='host.zone.com')
using the CLI:
ib object -n record:host create -a '{"ipv4addrs":[{"ipv4addr":"10.222.0.12"}],"name":"host.zone.com"}'
Schedule an object creation¶
Using the client:
There is a keyword argument schedule_time
which comes in handy to schedule an object creation.
network = client.get_object('network')
network.create(schedule_time=1367752903, network='10.1.0.0/16')
using the CLI:
There is an option --schedule-time
that can be used with the create
command.
ib object -n network create -a '{"network":"10.1.0.0/16"}' --schedule-time=1367752903
The response will contain the reference of the created scheduled task
"scheduledtask/b25lLnF1ZXVlZF90YXNrJDY:6/PENDING"
Execute a function call¶
Using the client:
There is a handy method func_call
that helps to realize function calls easily. Admitting we have created the network
10.1.0.0/16
with the previous operation and we have its reference, we can do this to get the three next available
/24 networks excluding 10.1.1.0/24
and 10.1.3.0/24
network = client.get_object('network')
network.func_call(object_ref='network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0/16/default',
function_name='next_available_network', exclude=['10.1.1.0/24', '10.1.3.0/24'], cidr=24, num=3)
using the CLI:
There is an object
sub-command func-call
which allows the same operation to be performed as above.
ib object -n network func-call -o network/ZG5zLm5ldHdvcmskMTAuMS4wLjAvMTYvMA:10.1.0.0/16/default -n next_available_network\
-a '{"exclude":["10.1.1.0/24","10.1.3.0/24"],"cidr":24,"num":3}'
You will get something similar to the following:
{
"networks": [
"10.1.0.0/24",
"10.1.2.0/24",
"10.1.4.0/24"
]
}
Upload a file to the appliance¶
To upload a file to the appliance, we first need to warn him.
Using the client:
file_op = client.get_object('fileop')
file_op.func_call(function_name='uploadinit')
using the CLI:
ib object -n fileop func-call -n uploadinit -a '{}'
Note that even if the function does not take an argument you need the provide an empty json, otherwise you will get an error.
The appliance will return an url where to upload the file and a token value like following:
{
"token": "eJydkMFOwzAMhu9+k......",
"url": "https://192.168.1.2/...."
}
The file can then be uploaded to the specified url. For that we will use the underlying requests.Session object used by our client instance since there is no particular method dedicated to upload files.
Using the client:
session = client.session
files = {'import_file': open('foo.txt', 'rb')}
session.post('https://192.168.1.2/....', files=files)
using the CLI:
ib
CLI utility does not have a native command to upload or download files since it is not his main purpose. You will
need another CLI utility to perform those actions. Two good options are curl and
httpie. You can install the latter with the following command (assuming you have pip installed):
pip install httpie
We will use it th show how to handle files. To perform the previous action, just type this:
http --verify=no -a username:password -f POST https://192.168.1.2/... import_file@foo.txt
Note
In the previous example, the filename is import_file because we did not specify any filename when performing
the action upload_init
like as stated in the
documentation
To better understand the syntax, you can take a look at httpie documentation.
Finally, we need to signal the appliance that the upload has been completed and that it needs to perform the requested action on the uploaded file. In this example, we will use setfiledest.
using the client:
file_op = client.get_object('fileop')
file_op.func_call(function_name='setfiledest', dest_path='/foo.txt', type='TFTP_FILE', token='eJydkMFOwzAMhu9+k...')
using the CLI:
ib object -n fileop func-call -n setdestfile -a '{"dest_path":"/foo.txt","type":"TFTP_FILE","token":"eJydkMFOwzAMhu9+k..."}'
Download a file from the appliance¶
To download a file from the appliance, we first need to select what to download, in this example it will be a backup.
Using the client:
file_op = client.get_object('fileop')
file_op.func_call(function_name='getgriddata', type='backup')
using the CLI:
ib object -n fileop func-call -n getgriddata -a '{"type":"backup"}'
The appliance will return a token and a URL from which the file should be downloaded:
{
"token": "eJydUMtuwyAQvO....",
"url": "https://192.168.1.2/...."
}
Now we can download the file.
Using the client:
session = client.session
r = session.get('https://192.168.1.2/....', stream=True)
with open('foo.txt', 'wb') as fd:
for chunk in r.iter_content(chunk_size=128):
fd.write(chunk)
using httpie CLI:
http --verify=no -a username:password --download https://192.168.1.2/....
After the download has been completed, we can signal the appliance that the operation is done by calling downloadcomplete and passing the token we have retrieved in the first step.
Using the client:
file_op = client.get_object('fileop')
file_op.func_call(function_name='downloadcomplete', token='eJydUMtuwyAQvO....')
using the CLI:
ib object -n fileop func-call -n downloadcomplete -a '{"token":"eJydUMtuwyAQvO...."}'
Retrieve a lot of data¶
If you want to retrieve hundreds or thousands of objects in one call, the client method get
is not suitable. There
is a more convenient method get_multiple
which takes care to not need a lot of memory to retrieve objects. It's usage
is quite simple:
network = client.get_object('network')
for net in network.get_multiple(params={'network_view': 'default'}):
print(net) # do whatever you want with the retrieved network
There is no equivalent for the CLI
Also, if you just need to count a set of objects matching specific rules, there is a handy method count
that you
can used.
Using the client:
network = client.get_object('network')
network.count(params={'network_view': 'default', 'comment~': 'sample'})
using the CLI:
ib object -n network count -p '{"network_view":"default","comment~":"sample"}'
Execute a custom request¶
One specificity of infoblox api is to perform many actions in one HTTP call. It is done via the
request object. With ib-client you can perform the same
thing by using the client custom_request
method or the request
sub command if you use the CLI. We will take one
example of this tutorial which consists
of getting a host record with the name test.somewhere.com, saved its reference to the state object and used it for an
update operation.
Using the client:
data = [
{
"method": "STATE:ASSIGN",
"data": {
"host_name": "test.somewhere.com"
}
},
{
"method": "GET",
"object": "record:host",
"data": {
"name": "##STATE:host_name:##"
},
"assign_state": {
"host_ref": "_ref"
},
"enable_substitution": True,
"discard": True
},
{
"method": "PUT",
"object": "##STATE:host_ref:##",
"enable_substitution": True,
"data": {
"comment": "new comment"
},
"args": {
"_return_fields": "comment"
},
"assign_state": {
"updated_comment": "comment"
},
"discard": True
},
{
"method": "STATE:DISPLAY"
}
]
client.custom_request(data)
Simple enough! The hardest part is to know how to format your request.
Using the CLI:
ib request '[{"method":"STATE:ASSIGN","data":{"host_name":"test.somewhere.com"}},{"method":"GET","object":"record:host",\
"data":{"name":"##STATE:host_name:##"},"assign_state":{"host_ref": "_ref"},"enable_substitution": true,"discard": true},\
{"method":"PUT","object":"##STATE:host_ref:##","enable_substitution": true,"data":{"comment":"new comment"},"args":\
{"_return_fields":"comment"},"assign_state":{"updated_comment":"comment"},"discard":true},{"method":"STATE:DISPLAY"}]'
Like you see, it is definitely not convenient to perform your operation this way. This is why the command accepts a -j
option where you can pass the path of a json file which contains the body of the request. Assuming you have a json
file foo.json
in your working directory with this content:
[{
"method": "STATE:ASSIGN",
"data": {
"host_name": "test.somewhere.com"
}
},
{
"method": "GET",
"object": "record:host",
"data": {
"name": "##STATE:host_name:##"
},
"assign_state": {
"host_ref": "_ref"
},
"enable_substitution": true,
"discard": true
},
{
"method": "PUT",
"object": "##STATE:host_ref:##",
"enable_substitution": true,
"data": {
"comment": "new comment"
},
"args": {
"_return_fields": "comment"
},
"assign_state": {
"updated_comment": "comment"
},
"discard": true
},
{
"method": "STATE:DISPLAY"
}
]
You can run this command instead:
ib request -j foo.json
Simple enough! The result of this request will look like the following:
{
"host_name": "test.somewhere.com",
"host_ref": "record:host/ZG5...zdA:test.somewhere.com/default",
"updated_comment": "new comment"
}