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!

Published Jul 09, 2015
Version 1.0
  • 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

  • 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.

     

     

  • 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"

                            }

                        }

                    ]

                }

     

  • 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.

  • 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
  • i want to get only one data like my picture,how do i filter ?