cancel
Showing results for 
Search instead for 
Did you mean: 
Login & Join the DevCentral Connects Group to watch the Recorded LiveStream (May 12) on Basic iControl Security - show notes included.
JRahm
Community Manager
Community Manager

iControl REST. It’s iControl SOAP’s baby brother, introduced back in TMOS version 11.4 as an early access feature but was released fully in version 11.5.

0151T000003d6Y3QAI.png

 Several articles on basic usage have been written on iControl REST (see the resources at the bottom of this article) so the intent here isn’t basic use, but rather to demystify some of the finer details of using the API. This article is the first of a four part series and will cover how the URI path plays a role in how the API functions.

Examining the REST interface URI

With iControl SOAP, all the interfaces and methods are defined in the WSDLs. With REST, the bulk of the interface and method is part of the URI. Take for example a request to get the list of iRules on a BIG-IP.

https://x.x.x.x/mgmt/tm/ltm/rule

With a simple get request with the appropriate headers and credentials (see below for curl and python examples,) this breaks down to the Base URI, the Module URI, and the Sub-Module URI.

#python example
>>> import requests
>>> import json
>>> b = requests.session()
>>> b.auth = ('admin', 'admin')
>>> b.verify = False
>>> b.headers.update({'Content-Type':'application/json'})
>>> b.get('https://172.16.44.128/mgmt/tm/ltm/rule')


#curl example
curl -k -u admin:admin -H “Content-Type: application/json” -X GET https://172.16.44.128/mgmt/tm/ltm/rule

Beyond the Sub-Module URI is the component URI.

https://x.x.x.x/mgmt/tm/ltm/rule/testlog

The component URI is the spot that snags most beginners. When creating a new configuration object on an F5, it is fairly obvious which URI to use for the REST call. If you were creating a new virtual server, it would be /mgmt/tm/ltm/virtual, while a new pool would be /mgmt/tm/ltm/pool. Thus a REST call to create a new pool on an LTM with the IP address 172.16.44.128 would look like the following:

#python example
>>> import requests
>>> import json
>>> b = requests.session()
>>> b.auth = ('admin', 'admin')
>>> b.verify = False
>>> b.headers.update({'Content-Type':'application/json'})

>>> pm = ['192.168.25.32:80', '192.168.25.33:80']
>>> payload = { }
>>> payload['kind'] = 'tm:ltm:pool:poolstate'
>>> payload['name'] = 'tcb-pool'
>>> payload['members'] = [ {'kind': 'ltm:pool:members', 'name': member } for member in pm]
>>> b.post('https://172.16.44.128/mgmt/tm/ltm/pool', data=json.dumps(payload))


#curl example
curl -k -u admin:admin -H "Content-Type: \
application/json" -X POST -d \
'{"name":"tcb-pool","members":[ \
{"name":"192.168.25.32:80","description":"first member”}, \
{"name":"192.168.25.33:80","description":"second member”}  ] }' \
https://172.16.44.128/mgmt/tm/ltm/pool

The call would create the pool “tcb-pool” with members at 192.168.25.32:80 and 192.168.25.33:80.  All other aspects of the pool would be the defaults.  Thus this pool would be created in the Common partition, have the Round Robin load balancing method, and no monitor. At first glance, some programmers would then modify the pool “tcb-pool” with a command like the following (same payload in python, added the .text attribute to see the error response on the requests object):

#python example
>>> b.put('https://172.16.44.128/mgmt/tm/ltm/pool', data=json.dumps(payload)).text
#return data
u'{"code":403,"message":"Operation is not supported on component /ltm/pool.","errorStack":[]}'

#curl example
curl -k -u admin:admin -H "Content-Type: \
application/json" -X PUT -d \
'{"name":"tcb-pool","members":[ \
{"name":"192.168.25.32:80","description":"first member"}
{"name":"192.168.25.33:80","description":"second member"} ] }' \
https://172.16.44.128/mgmt/tm/ltm/pool
#return data
{"code":403,"message":"Operation is not supported on component /ltm/pool.","errorStack":[]}

You can see because they use the sub module URI used to create the pool this returns a 403 error. The command fails because one is trying to modify a specific pool at the generic pool level. Now that the pool exists, one must use the URI that specifies the pool. Thus, the correct command would be:

#python example
>>> b.put('https://172.16.44.128/mgmt/tm/ltm/pool/~Common~tcb-pool', data=json.dumps(payload))

#curl example
curl -k -u admin:admin -H "Content-Type: \
application/json" -X PUT -d \
'{"members":[ \
{"name":"192.168.25.32:80","description":"first member"}
{"name":"192.168.25.33:80","description":"second member"} ] }' \
https://172.16.44.128/mgmt/tm/ltm/pool/~Common~tcb-pool

We add the ~Common~ in front of the pool name because it is in the Common partition. However, this would also work with https://172.16.44.128/mgmt/tm/ltm/pool/tcb-pool. It is just good practice to explicitly insert the partition name since not all configuration objects will be in the default Common partition. Because we specify the pool in the URI, it is no longer necessary to have the “name” key value pair.

In practice, programmers usually correctly modify items such as virtual servers and pools. However, we encounter this confusion much more often in configuration items that are ifiles. This may be because the creation of configuration items that are ifiles is a 3-step process. For instance, in order to create an external data group, one would first scp the file to 172.16.44.128/config/filestore/data_mda_1, then issue 2 Rest commands:

curl -sk -u admin:admin -H "Content-Type: application/json" -X POST -d '{"name":"data_mda_1","type":"string","source-path":"file:///config/filestore/data_mda_1"}' https://172.16.44.128/mgmt/tm/sys/file/data-group
curl -sk -u admin:admin -H "Content-Type: application/json" -X POST -d '{"name":"dg_mda","external-file-name":"/Common/data_mda_1"}' https://172.16.44.128/mgmt/tm/ltm/data-group/external/

To update the external data group, many programmers first try something like the following:

curl -sk -u admin:admin -H "Content-Type: application/json" -X POST -d '{"name":"data_mda_2","type":"string","source-path":"file:///config/filestore/data_mda_2”}’ https://172.16.44.128/mgmt/tm/sys/file/data-group
curl -sk -u admin:admin -H "Content-Type: application/json" -X PUT -d '{"name":"dg_mda","external-file-name":"/Common/data_mda_2"}' https://172.16.44.128/mgmt/tm/ltm/data-group/external/

The first command works because we are creating a new ifile object. However, the second command fails because we are trying to modify a specific external data group at the generic external data group level. The proper command is:

curl -sk -u admin:admin -H "Content-Type: application/json" -X PUT -d '{"external-file-name":"/Common/data_mda_2"}' https://172.16.44.128/mgmt/tm/ltm/data-group/external/dg_mda

The python code gets a little more complex with the data-group examples, so I've uploaded it to the codeshare here. Much thanks to Pat Chang for the bulk of the content in this article. Stay tuned for part 2, where we'll cover sub collections and how to use them.

Comments
rohans77
Nimbostratus
Nimbostratus
Thanks Jason. This is really awesome.
oogabooga_13071
Altocumulus
Altocumulus
Teaching Network guys to program with purpose... nice one
Andrew_Le_12873
Nimbostratus
Nimbostratus
Good info here.
Curtis_Owings_2
Nimbostratus
Nimbostratus
Is there some sort of map from the GUI to these URI's? For example, if I want to see the output from System > File Management > SSL Certificate List: what is that in the URI? /mgmt/tm/???/???/???
JRahm
Community Manager
Community Manager
Hi Curtis, the map would be GUI->tmsh. The rest API is a wrapper for tmsh.
Ai_Bui_239105
Nimbostratus
Nimbostratus
what would the curl command will be when user need to update an internal data group?
JOBrien2019
Nimbostratus
Nimbostratus

You said there would be some articles about basic icontrol usage in a "resources" section in this article. But I'm not seeing that section (I'm on Firefox). I've been searching around trying to find them and I just can't. Can you link that series?

 

Version history
Last update:
‎17-Jun-2015 08:00
Updated by:
Contributors