Forum Discussion

naladar_65658's avatar
naladar_65658
Icon for Altostratus rankAltostratus
Sep 09, 2008

Can you refer to a data group from within a switch?

Is it possible to refer to a data group from within a switch? Also, a big thank you to Joe for helping me get this far! You guys are awesome. I have only been at this about a week, but I have learned a ton by reading posts and wiki's here on the f5 site!

 

 

Here is a working code snippet:

 

 

switch -glob [string tolower [HTTP::uri]] {

 

"/fc/*" -

 

"/wpi/*" {

 

pool WWW2_Pool

 

}

 

default {

 

pool WWW3_Pool

 

}

 

 

Is it possible for me to put those strings into a string type data group (we will call it WWW2_uri) and just call the data group instead of each string? Maybe something like this?:

 

 

 

switch -glob [string tolower [HTTP::uri]] {

 

$::WWW2_uri {

 

pool WWW2_Pool

 

}

 

default {

 

pool WWW3_Pool

 

}

 

}

 

 

 

I did read the Controlling Bots iRule in the wiki, but I was hoping there was a way to call the external data group without re-writing it in a long if/else statement.

 

3 Replies

  • I don't think there is a way to combine switch with matchclass. if/else with matchclass seems like the option. I suppose you could get fancy and create a list of the datagroups you want to test against and then loop through them using foreach and exit the loop once you find a match with 'break'. I don't think it would be very elegant though.

     

     

    Aaron
  • Thanks for the response hoolio. The code I was showing actually used to be written in an if/elseif statement, but with Joe's help I was able to convert it to a switch so it would be more efficient.

     

     

    I was thinking about this at lunch and I would be willing to bet that even if I could combine the two it would defeat the purpose of the having everything in a switch to begin with. The switch gets processed once, while if/elseif requires a lot more processing. If I told the switch to go get a data group, it would just add to the processing requirements. So although the data groups might make it easier manage (if it could be done at all) in the end it doesn't make it more efficient because of the extra calls/fetching.

     

     

    Does that sound even remotely right?
  • I think a switch and an if/elseif/else chain are pretty close in terms of efficiency. It might be better to have a single datagroup with the URI tokens followed by the corresponding pool. If you need to support wildcards in the class, you can use foreach instead of findclass.

    Here is a sample class:

     
     class paths_pool_class { 
        "/path1* pool2" 
        "/path2/test* pool2" 
        "/path3/ pool1" 
     } 
     

    You could then use a foreach loop to find a matching line in the class. If you parse the second field in the line, you could then specify the pool. There is an example of using foreach and string match to do wildcard matching (Click here). You can use getfield to parse the pool name (Click here).

     
     when HTTP_REQUEST {   
      
           Check the requested path against the paths pool class 
          foreach element $::paths_pool_class {   
          
             log local0. "Current \$element: $element"   
      
             if {[string match -nocase $element [HTTP::path]]}{   
          
                log local0. "Matched \$element: $element.  Exiting loop" 
                break 
             } 
             set parsed_pool [getfield $element " " 2] 
             log local0. "\$parsed_pool: $parsed_pool" 
      
              Check if parsed pool is up 
             if {[active_members $parsed_pool]}{ 
                log local0. "pool $parsed_pool has active members" 
                pool $parsed_pool 
             } else { 
                 Take some default action if the parsed pool is down? 
                HTTP::redirect "http://maintenance.example.com" 
             } 
          }   
       } 
     

    I'm not sure if the active_members command will kick out a TCL error if the pool doesn't exist. If it does, you might want to use catch to trap the error. You can use something like this to do so:

     
     if {[catch {active_members $parsed_pool} result]}{ 
         There was an error 
        log local0. "Error. Catch result: $result" 
     } else { 
        log local0. "OK. Catch result: $result" 
     } 
      
      
     Aaron