Demystifying iControl REST Part 3 - How to pass query parameters and tmsh options
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!
- JRahmAdminper 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.
- ChadU_140502AltostratusCan 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
- gvo_142555NimbostratusI'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?
- mraful_64014Nimbostratus@jrahm. Actually you have escape the dollar sign... at least on curl. getting ready to try via the python requests module shortly.
- JRahm_128324Historic F5 Account@mraful, Try https://10.19.1.10/mgmt/tm/sys/software/status/stats?$select=active,version,build instead.
- mraful_64014NimbostratusThis 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
- mraful_64014NimbostratusThis 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
- JRahmAdmin@mayouche, can you move your question to Q&A with a link to this article and provide more details? Thanks, Jason
- mayouche_162667NimbostratusI 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
- JRahmAdminI'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.