Forum Discussion

eLeCtRoN's avatar
eLeCtRoN
Icon for Cirrus rankCirrus
May 08, 2018

iRule for Version check with dependent pool selection

Hello,

I have a scenario, my web developers want a dynamic pool selection which depents on a Version No., my idea was to make a curl get request with credentials (with a simple http basic auth) and I get back something like that. (result from the curl get)

 

{
"build" : {
"version" : "20001.0.1",
"artifact" : "calculator-web-service",
"name" : "calculator-web-service",
...

 

Now the user access the VIP maybe 10.10.10.10/Version.20001.0.1 and I want to compare with my curl query, is it the same version balance to pool A is it different balance to pool B. Is that possible and how could I realize that, Im not so familiar with iRules ! Maybe I could get an example ? Or a another idea how can I realize this.

 

THX Manuel

 

  • Hi,

     

    just want to clarify your need before to give your an solution.

     

    Use case:

     

    • User connect to VIP:
    • F5 made a curl on one poolmember hosted by poolA and poolB?
    • If poolmember have the same version that poolA you redirect user on poolA
    • If poolmember have the same version that poolB you redirect user on poolB
    • else defautl pool.

    We are agree that you want curl a backend server? to retrieve Version No...

     

    You can validate please.

     

    Regards.

     

  • Hi youssef,

     

    yes your explanation is correct but, I have a pool member with a static version this version will be never change, and is in the pool A, the poolmember with the changing version is in pool B, connect the user to should check the version from poolmeber in pool B is it the same balance to pool B but is the version different balance all to pool A and else to default pool

     

    THX

     

    Manuel

     

  • Hi Youssef,

     

    I spoke with the developers again and I have to correct my anserwer, I thing your questions or explainations are correct.

     

    Thats the correct scenario:

     

    There are pool A with software version Y and pool B with software version X.

     

    At a certain time then software version Z is deployed on the pool A and software version Y migrates on the pool B.

     

    This process happens every few weeks.

     

    The user always enters:

     

    http://abc.de/X or http://abc.de/Y etc…

     

    With a GET query I can read from a node in a pool, which software version has this node:

     

    Example of a CURL query:

     

    rdexec 1 curl --user user: password http://192.168.1.1/info

     

    And the output is something like:

     

     

    {
       "build": {
       "version": "20001.0.1",
    

     

    I hope it is not too messed up now 😉

     

    Regards Manuel

     

  • I may not have fully understood but here is a simple iRule I've put together which may work, or at least give you an idea of where to go next. Unfortunately there is no why to interrogate the result of a health monitor by an iRule but you can can determine if you have active members - which is reliant on the monitor.

    From what I understand, incoming requests will have the version number in the URI and from that you want to dynamically select the pool or pool member.

    If you have a one to one relationship between pool names and version you can dynamically select the pool based on URI - you will however have to maintain a different pool for every new version.

     

    when HTTP_REQUEST {
    
        set defaultPool "MY_DEFAULT_POOL_NAME"
         use getfield to pick 'field1'of the URI https://host.com/field1/field2
        set dynamicPool [getfield [HTTP::uri] "/" 2]
        log local0. "Pool: $dynamicPool derived from URI"
    
        if {$dynamicPool ne ""} {
             place commands using dynamicPool in catch statement
             this will silently catch the TCL error in the event 
             the pool doesn't exist
            if {[catch {
                if {[active_members $dynamicPool] > 0} {
                    log local0. "load balancing to pool: $dynamicPool"
                    pool $dynamicPool
                }
            } catchErr ]} {
                 select default pool if dynamicPool doesn't exist
                log local0. "unable to select pool based on URI, will use default  - error: $catchErr'"
                pool $defaultPool
            }
        } else {
            log local0. "Error - pool value empty, setting to default"
            pool $defaultPool
        }
    
    }
    

     

    Please note this iRule has only tested for syntax errors

  • Hello Manuel,

     

    I'am sorry for te delate I was off :-). So you can use sideband connections:

     

    https://clouddocs.f5.com/api/irules/SIDEBAND.html

     

    Using this command (1.1.1.1 will be your backend. just be carefull, sideband working only in http:

     

    $1

     

    So I write your an Irule that allow you to retrieve version from backend node. I have not tested it but you have all elements that allow you to go ahead. Below Irule you need:

     

    when HTTP_REQUEST {
    
     following code allow you to connect to your backend (1.1.1.1 1.1.1.1 will be your backend server in the pool)
    
    if {[catch {connect -timeout 1000 -idle 30 -status conn_status 1.1.1.1:80} conn_id] == 0 && $conn_id ne ""}{
        log local0. "Connect returns: $conn_id and conn status: $conn_status"
    } else {
        log local0. "Connection could not be established to backend node"
    }
    
     we set var tha we will send to backend, you can use post, get put as you want (mybackend_hostname.com will be the backend hostname)
    
    set data_validate "GET /info HTTP/1.1\r\nHost: mybackend_hostname.com\r\nConnection: keep-alive\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36\r\nAccept-Language: fr,en;q=0.9\r\n\r\n"
    
     we sent date
    
    set send_bytes [send -timeout 1000 -status send_status $conn_id $data_validate]
    log local0. "AAA Sent $send_bytes with status $send_status"
    
     we receive data
    
    set recv_data [recv -timeout 1000 $conn_id]
    log local0. "1 - ([string length $recv_data]): $recv_data"
    
    retrieve version info from response
    regexp {.*\"sourceGuid\":[^\"]+\"([^\"]+)\"} $recv_data -> version
    log local0. "Node version $version"
    
    }
    

    Let me now if you need additional help in order to finalize your irule.

     

  • Hello Manuel,

     

    have you been able to test my irule?

     

    regards