Technical Articles
F5 SMEs share good practice.
cancel
Showing results for 
Search instead for 
Did you mean: 
Custom Alert Banner
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 released fully in version 11.5.

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. The first article covered URI specifics, the second article discussed subcollections, and this third article will cover query parameters.

Query Parameter Definitions

F5 has documented a number of query parameters that can be passed into iControl ReST calls in order to modify their behavior. The first set follows the OData (open data protocol) standard. The filter parameter also supports several operators.

  • $filter
  • $select
  • $skip
  • $top

Yes, the dollar sign is important and necessary on these parameters. The operators you can use on these parameters are below. Note that the eq operator can only be used with the filter.

  • eq - equal
  • ne - not equal
  • lt - less than
  • le - less than or equal
  • gt - greater than
  • ge - greater than or equal
  • Logical Operators:
    • and
    • or
    • not

Beyond the OData parameters, there are a few custom parameters as well.

  • expandSubcollections - allows you to get the subcollection data in the initial request for objects that have subcollections.
  • options - allows you to add arguments to the tmsh equivalent command. An example will be shown below.
  • ver - This is for the specific TMOS version. Setting this parameter guarantees consistent behavior through code upgrades. Please note that the JSON return data for a number of calls has changed between the initial release in 11.5.0 and the current release. No items have been removed, but key/value pairs in the output have been added.

Note the lack of a dollar sign on the custom parameters.

Example #1 - Filter

Now that we have the parameters and operators defined, let’s take a look at some examples. First, we’ll take a look at the $filter parameter. If you want to limit your results to a particular partition, your URL will look something like this:

https://172.16.44.128/mgmt/tm/ltm/pool?$filter=partition eq staging
https://172.16.44.128/mgmt/tm/ltm/pool?$filter=partition%20eq%20staging
https://172.16.44.128/mgmt/tm/ltm/pool?$filter=partition+eq+staging

As long as your client tool supports it, any of these formats will work, but the resulting selfLink reflects the latter format:

 

Example #2 - Select

I didn’t post the return data from example 1 because it’s a lot of data, even for a small set of returned results. Most of it is all the fields in a pool that are there and important, but default and not of as immediate importance as others. This is where the $select parameter comes in. If you just want to take a look at the name of the pool and say the load balancing mode, your URL will look like this (still filtering for the staging partition:)

https://172.16.44.128/mgmt/tm/ltm/pool?$filter=partition+eq+staging&$select=name,loadBalancingMode

This results in a smaller subset of data limited to the fields we “selected"

items: [5]
0:  {
name: "sp1"
loadBalancingMode: "round-robin"
}-
1:  {
name: "sp2"
loadBalancingMode: "round-robin"
}-
2:  {
name: "sp3"
loadBalancingMode: "round-robin"
}

Example #3 - Top & Skip

For larger sets of data, you can page through the objects in chunks with $top and $skip. If $skip is not specified when $top is used, it behaves as though set to 0. Please note, however, that paging is restricted to collections and sub collections, so whereas this would work to page through the defined data groups, it would not work to page through the records of a data group. Let’s add the top parameter to our previous URL:

https://172.16.44.128/mgmt/tm/ltm/pool?$filter=partition eq staging&$select=name,loadBalancingMode&$top=2

#Results
{
kind: "tm:ltm:pool:poolcollectionstate"
selfLink: "https://localhost/mgmt/tm/ltm/pool?$filter=partition+eq+staging&$select=name%2CloadBalancingMode&$top=2&ver=12.0.0"
currentItemCount: 2
itemsPerPage: 2
pageIndex: 1
startIndex: 1
totalItems: 5
totalPages: 3
items: [2]
0:  {
name: "sp1"
loadBalancingMode: "round-robin"
}
-
1:  {
name: "sp2"
loadBalancingMode: "round-robin"
}
-
-
nextLink: "https://localhost/mgmt/tm/ltm/pool?$filter=partition+eq+staging&$select=name%2CloadBalancingMode&$top=2&$skip=2&ver=12.0.0"

So we got the same data back as before, only 2 items instead of the original 5, as well as some additional fields that weren’t there previously. Note that once $top is used, the key/value pairs “nextLink”, “currentItems”, and “totalItems” are added to the response. “nextLink” is the URI that will grab the next $top number of results from the query. If you parse this value and use it (once you have replaced the localhost with your actual host information), you will not have to perform any paging calculations. “currentItems” tells you how many items have been returned in the current call. If this value is less than $top, then you know you have reached the end of the items. “totalItems” tells you how many items would be returned if one did not page using $top.

Example #4 - Options

For this next example, we’ll start with tmsh. If you want to get the connections on the BIG-IP, you type “tmsh show sys conn” at the command line. This can be a very large set of data, however, so there are options on the command line to narrow this down, like cs-client-addr, cs-client-port, and so on. So a narrowed down request at the command line would look like “tmsh show sys conn cs-client-addr 10.0.0.1 cs-client-port 62223.” To translate this command to an API request, you need to use the options parameter

https://172.16.44.128/mgmt/tm/sys/connection?options=cs-server-addr+192.168.102.50+cs-server-port+80

#Results
{
kind: "tm:sys:connection:connectionstats"
selfLink: "https://localhost/mgmt/tm/sys/connection?options=cs-server-addr+192.168.102.50+cs-server-port+80&ver=11.6.0"
apiRawValues: {
apiAnonymous: "Sys::Connections 192.168.102.5:57359 192.168.102.50:80 192.168.102.5:57359 192.168.103.11:8080 tcp 2 (tmm: 1) none Total records returned: 1 "
}-
}

Example #5 - Expanding Subcollections

For our final example, we’ll use the expandSubcollections parameter. This is useful for querying objects like pools that have subcollections. Without the parameter specified, the pool data is returned with the specification that pool members is a subcollection, but doesn’t return the set of pool members. By providing the parameter, the pool members are returned along with the pool definition (only first one shown for brevity.)

https://172.16.44.128/mgmt/tm/ltm/pool/testpool?expandSubcollections=true

#Results
{
kind: "tm:ltm:pool:poolstate"
name: "testpool"
fullPath: "testpool"
generation: 1
selfLink: "https://localhost/mgmt/tm/ltm/pool/testpool?expandSubcollections=true&ver=11.6.0"
allowNat: "yes"
allowSnat: "yes"
ignorePersistedWeight: "disabled"
ipTosToClient: "pass-through"
ipTosToServer: "pass-through"
linkQosToClient: "pass-through"
linkQosToServer: "pass-through"
loadBalancingMode: "round-robin"
minActiveMembers: 0
minUpMembers: 0
minUpMembersAction: "failover"
minUpMembersChecking: "disabled"
queueDepthLimit: 0
queueOnConnectionLimit: "disabled"
queueTimeLimit: 0
reselectTries: 0
serviceDownAction: "none"
slowRampTime: 10
membersReference: {
link: "https://localhost/mgmt/tm/ltm/pool/~Common~testpool/members?ver=11.6.0"
isSubcollection: true
items: [7]
0:  {
kind: "tm:ltm:pool:members:membersstate"
name: "192.168.103.10:80"
partition: "Common"
fullPath: "/Common/192.168.103.10:80"
generation: 1
selfLink: "https://localhost/mgmt/tm/ltm/pool/~Common~testpool/members/~Common~192.168.103.10:80?ver=11.6.0"
address: "192.168.103.10"
connectionLimit: 0
dynamicRatio: 1
ephemeral: "false"
fqdn: {
autopopulate: "disabled"
}
...

Example #6 - Careful! Select Revisited

If you want to select just the name and address from the pool members in the previous example, it's not as simple as adding the $select=name,address to that query. Remember from the earlier article about your object/component/sub-component tiers. Instead, you need to specify the members subcollection in the URL, then attach your select parameter.

https://172.16.44.128/mgmt/tm/ltm/pool/testpool/members?$select=name,address
#Results
{
kind: "tm:ltm:pool:members:memberscollectionstate"
selfLink: "https://localhost/mgmt/tm/ltm/pool/testpool/members?$select=name%2Caddress&ver=11.6.0"
items: [7]
0:  {
name: "192.168.103.10:80"
address: "192.168.103.10"
}-
1:  {
name: "192.168.103.10:8080"
address: "192.168.103.10"
}-
2:  {
name: "192.168.103.11:80"
address: "192.168.103.11"
}
...

A Whiteboard Wednesday Shout Out to iControl REST

I’ve summarized a lot of what was covered in this article in the following Whiteboard Wednesday video. Enjoy!

Comments
tatmotiv
Cirrostratus
Cirrostratus
Great article, especially since it explains many features which are not covered at all in the official iControl REST documentation! Many Thanks.
Patrick_Chang_7
Historic F5 Account
It is very important to filter your results when you are expecting a lot of output in the return. One can easily cause problems by overloading the management network.
Andrew_Le_12873
Nimbostratus
Nimbostratus
Can you get example for "options" using a component other than 'sys connection' ?
bahoug_11846
Nimbostratus
Nimbostratus
Can this be used for listing/deleting persistence records? Looking at the available commands it doesn't appear to be possible.
JRahm_128324
Historic F5 Account
@bahoug, yes this is possible: https://172.16.44.15/mgmt/tm/ltm/persistence/persist-records?options=client-addr+192.168.102.1 Results from my local query: { kind: "tm:ltm:persistence:persist-records:persist-recordsstats" selfLink: "https://localhost/mgmt/tm/ltm/persistence/persist-records?options=client-addr+192.168.102.1&ver=12.0.0" apiRawValues: { apiAnonymous: "Sys::Persistent Connections source-address 192.168.102.1 192.168.102.60:80 192.168.103.10:80 (tmm: 0) Total records returned: 1 " }- }
bahoug_11846
Nimbostratus
Nimbostratus
@JRahm I'm guessing the reason I cant get it to work is I am running 11.5.1. I see in your self link you are using v12.0. Your example is exactly what I am looking for to delete persistence records and system connections. I've seen a few other examples that call cli scripts from the restAPI, however its not as elegant as just being able to use the restAPI. BTW this is a great article thanks for putting it together.
JRahm
Community Manager
Community Manager
I'll fire up an 11.5 image tomorrow and test, it should work as is (minus the version parameter) in all versions, but I'll take a look at the tmsh command in 11.5 and make sure the rest version works as well.
mayouche_162667
Nimbostratus
Nimbostratus
I was able to run these examples against my environment running version 11.5.3 i have a couple of questions: I'm getting could not resolve GET when using in version 11.5.3 Does Anybody have tips on how to manipulate the output to get a clean formatting? Thank you
JRahm
Community Manager
Community Manager
@mayouche, can you move your question to Q&A with a link to this article and provide more details? Thanks, Jason
mraful_64014
Nimbostratus
Nimbostratus
This doesn't work everywhere on all collections. For example, if I am looking for the software version and hotfix currently running, the select has no effect here: curl -k -u admin:myPassword -H "Content-Type: application/json" -X GET https://10.19.1.10/mgmt/tm/sys/software/status?$select=active,version,build -d "" | python -m json.tool
mraful_64014
Nimbostratus
Nimbostratus
This doesn't work everywhere on all collections. For example, if I am looking for the software version and hotfix currently running, the select has no effect here: curl -k -u admin:myPassword -H "Content-Type: application/json" -X GET https://10.19.1.10/mgmt/tm/sys/software/status?$select=active,version,build -d "" | python -m json.tool. Nothing gets filtered. I get everything
JRahm_128324
Historic F5 Account
@mraful, Try https://10.19.1.10/mgmt/tm/sys/software/status/stats?$select=active,version,build instead.
mraful_64014
Nimbostratus
Nimbostratus
@jrahm. Actually you have escape the dollar sign... at least on curl. getting ready to try via the python requests module shortly.
gvo_142555
Nimbostratus
Nimbostratus
I'm looking for a way to read the total number of persist-records without the actual records. So I can check if the cluster is in sync. How can I accomplish this with a Rest API call?
ChadU_140502
Altostratus
Altostratus
Can you filter on anything other than the partition attribute? Only being able to filter on that attribute seems to have little value. When I try other attributes I get an error like these: Query parameter $filter has invalid value allowNat eq yes. Query parameter $filter has invalid value monitor eq ~Common~http. I'm testing against 11.5.4
JRahm
Community Manager
Community Manager
per the user guide, the odata filter parameter is not fully implemented, so partition at this point is the only supported function for most modules. ASM, however, does support more filter functionality. Please consult the user guide.

In case somebody wants to dig a bit deeper into the supported OData features:

 

http://www.odata.org/odata-services/

 

/Patrik

 

mkolozs_236219
Nimbostratus
Nimbostratus

Great article! It helped me overcome some of the filtering issues I had with BIG-IQ CM REST API as well. However, one that I am not able to figure out yet is to select BIG-IP hostnames form a dynamic device group:

 

Like GET: https://{{bigiq_mgmt}}/mgmt/shared/resolver/device-groups//devices?$select=hostname

 

It still returns the full details of all devices in that group. In case someone has an advice on how to get only the devices hostnammes, managementAddress, that would be much appreciated.

 

clazba
Nimbostratus
Nimbostratus

Curl request for istats if anyone's interested

curl -sk GET https://my_ip/mgmt/tm/ltm/rule/my_rule/stats?\$select=blocked_ips\&\$top=1 -H X-F5-Auth-Token:xxxxxxxxxxxxxxxxx | json_pp

Ben_Novak
F5 Employee
F5 Employee

Does f5's implementation of odata structures allow for filtering with "contains"?

 

ex. $filter=contains(hostname, 'gtm')

 

If so, can you provide an example?

 

Thanks,

 

michael_massey
Nimbostratus
Nimbostratus

Is there a way to filter on Subcollections? such as this.... mgmt/tm/ltm/pool?expandSubcollections=true&$filter=partition eq 'partition name' ..... This will display all the pools and their pool members but I want to further filter down and only show the partition, pool name, pool member, pool member ip and the monitor. I can't seem to find any query examples on how to filter or select within a Subcollection. Thanks

JRahm
Community Manager
Community Manager

You will want to script that, I don't think a single query will give you the granularity you are looking for, but I'd be happy to be corrected.

 

 

michael_massey
Nimbostratus
Nimbostratus

Thanks so much for your reply but I have found something that has got me the information that I needed. Le me know your thoughts. I will post my output below minus the server names for security purposes

 

https://f5_ip/mgmt/tm/ltm/pool?expandSubcollections=true&$select=name,partition,monitor,membersReference/items/name,membersReference/items/address

 

I want to give credit to a user on here named Michael Jenkins that led me to this answer from a previous post he made on this page.

https://devcentral.f5.com/s/feed/0D51T00006j28P0SAI

 

 

 

Sample output

"kind": "tm:ltm:pool:poolcollectionstate",

    "selfLink": "https://localhost/mgmt/tm/ltm/pool?$select=name%2Cpartition%2Cmonitor%2CmembersReference/items/name%2CmembersReference/items/address&expandSubcollections=true&ver=14.1.0.6",

    "items": [

        {

            "name": "poolname_removed-8105",

            "partition": "partitionname_removed",

            "monitor": "/Common/monitorname_removed",

            "membersReference": {

                "items": [

                    {

                        "name": "removed01:8105",

                        "address": "ip_removed%10",

                        "nameReference": {

                            "link": "https://localhost/mgmt/tm/ltm/node/~partitionname_removed~removed01:8105?ver=14.1.0.6"

                        }

                    },

                    {

                        "name": "removed02:8105",

                        "address": "removed%10",

                        "nameReference": {

                            "link": "https://localhost/mgmt/tm/ltm/node/~partitionname_removed~removed02:8105?ver=14.1.0.6"

                        }

                    }

                ]

            }

 

J-H_Johansen
Nimbostratus
Nimbostratus

Running version 14.1.2.6, how can I filter on date? I have an ASM where I want to get all requests after a certain date

https://{{hostname}}/mgmt/tm/asm/events/requests?$filter=requestPolicy/createdDatetime+gt+'2020-07-28T00:00:00Z'&$select=requestPolicy/name,requestPolicy/createdDatetime,virtualServerName,serverIp,id,url,acceptStatus,responseContentType,violations/violationReference,enforcementMode,responseDatetime,clientIp,enforcementState/attackTypeReferences&$top=1

The response is

{
    "totalPages": 0,
    "pageIndex": 1,
    "selfLink": "https://localhost/mgmt/tm/asm/events/requests?$top=1&$select=requestPolicy%2Fname%2CrequestPolicy%2FcreatedDatetime%2CvirtualServerName%2CserverIp%2Cid%2Curl%2CacceptStatus%2CresponseContentType%2Cviolations%2FviolationReference%2CenforcementMode%2CresponseDatetime%2CclientIp%2CenforcementState%2FattackTypeReferences&ver=14.1.2&$filter=requestPolicy%2FcreatedDatetime%20gt%20%272020-07-28T00%3A00%3A00Z%27",
    "kind": "tm:asm:events:requests:requestcollectionstate",
    "startIndex": 1,
    "itemsPerPage": 1,
    "totalItems": 0,
    "items": []
}

When I run a query filtering on a specific ASM policy name I receive over 30.000+ items/requests

https://{{hostname}}/mgmt/tm/asm/events/requests?$filter=requestPolicy/name+eq+'{{asm-policy-name}}'&$select=requestPolicy/name,requestPolicy/createdDatetime,virtualServerName,serverIp,id,url,acceptStatus,responseContentType,violations/violationReference,enforcementMode,responseDatetime,clientIp,enforcementState/attackTypeReferences&$top=1
{
    "totalPages": 31980,
    "pageIndex": 1,
    "selfLink": "https://localhost/mgmt/tm/asm/events/requests?$top=1&$select=requestPolicy%2Fname%2CrequestPolicy%2FcreatedDatetime%2CvirtualServerName%2CserverIp%2Cid%2Curl%2CacceptStatus%2CresponseContentType%2Cviolations%2FviolationReference%2CenforcementMode%2CresponseDatetime%2CclientIp%2CenforcementState%2FattackTypeReferences&ver=14.1.2&$filter=requestPolicy%2Fname%20eq%20%27<asm-policy-name>%27",
    "kind": "tm:asm:events:requests:requestcollectionstate",
    "startIndex": 1,
    "itemsPerPage": 1,
    "totalItems": 31980,
    "nextLink": "https://localhost/mgmt/tm/asm/events/requests?$skip=1&$top=1&$select=requestPolicy%2Fname%2CrequestPolicy%2FcreatedDatetime%2CvirtualServerName%2CserverIp%2Cid%2Curl%2CacceptStatus%2CresponseContentType%2Cviolations%2FviolationReference%2CenforcementMode%2CresponseDatetime%2CclientIp%2CenforcementState%2FattackTypeReferences&ver=14.1.2&$filter=requestPolicy%2Fname%20eq%20%27<asm-policy-name>%27",
    "items": [
        {
            ...
            "responseDatetime": "2020-07-29T08:40:20Z",
            ...
        }
    ]
}

I've also tried to run the same query with 'requestDatetime' but still no items returned.

J-H_Johansen
Nimbostratus
Nimbostratus

Nevermind, I figured it out. Looks like the $filter only works on the field 'requestDatetime'

https://{{hostname}}/mgmt/tm/asm/events/requests?$filter=requestDatetime+gt+'2020-07-28T00:00:00Z'&$top=1

 which can be combined with

https://{{hostname}}/mgmt/tm/asm/events/requests?$filter=requestPolicy/name+eq+'{{asm-policy-name}}'+and+requestDatetime+gt+'2020-07-29T00:00:00Z'&$top=25
yingwei
Nimbostratus
Nimbostratus

i want to get only one data like my picture,how do i filter ?

Version history
Last update:
‎09-Jul-2015 12:00
Updated by:
Contributors