Forum Discussion

Uber_Nathan_202's avatar
Uber_Nathan_202
Icon for Nimbostratus rankNimbostratus
May 21, 2015

iApp variable scope

Hi all,

I'm writing my first iApp to automate deployment of a few virtual servers, nodes, pools and iRule data-groups

I have finished the presentation section and am now starting on the implementation. One issue that I'm having though is referencing variables assigned from the presentation within tmsh::create, tmsh:modify etc

I can read the variables back fine within the base iApp, for example I have the following:

puts "Adding SNAT data.  $::private__privateAddr maps to $::public__publicAddr"

Which logs the following in scriptd.out:

Adding SNAT data.  xxx.xxx.xxx.xxx maps to xxx.xxx.xxx.xxx

Where I run into the issue though is referencing the same variables in tmsh::modify.

For example I have the following:

proc tmsh_modify { args } {
    set args [join $args]
    puts "tmsh modify $args"
    tmsh::modify $args
    return [lindex $args [lsearch -glob $args "*_*"]]
}

puts "Adding SNAT data.  $::private__privateAddr maps to $::public__publicAddr"

tmsh_modify { ltm data-group internal /Common/snat-map
  records add { 
    $::private__privateAddr { 
      data $::public__publicAddr
    } 
  }
}

This logs the following:

[root@ltm02-dev:Active:Changes Pending] config  tail -f /var/tmp/scriptd.out -n0
    Adding SNAT data.  xxx.xxx.xxx.xxx maps to xxx.xxx.xxx.xxx
    tmsh modify  ltm data-group internal /Common/snat-map
      records add { 
        $::private__privateAddr { 
          data $::public__publicAddr
        } 
      }

So from this I can see the variables are being treated as normal strings. As expected this errors out on the iApp creation screen:

script did not successfully complete: ("$::private__privateAddr" invalid address
    while executing
    "tmsh::modify $args"
    (procedure "tmsh_modify" line 4)
    invoked from within
    "tmsh_modify { ltm data-group internal /Common/snat-map
    records add { 
    $::private__privateAddr { 
    data $::public__publicAddr
    } ..." line:14)

I couldn't find any specific information on the scope of variables when used in this manner, perhaps it is just a simple issue of syntax.

I'd appreciate if someone can give me some guidance on this.

Thanks!

  • Scope is not the problem. Tcl treats anything inside curly braces as verbatim. Enclosed strings in quotes and escape each curly brace with a backslash.

     

    tmsh_modify "ltm data-group internal /Common/snat-map records add { $::private__privateAddr { data $::public__publicAddr }}"

     

  • Fred_Slater_856's avatar
    Fred_Slater_856
    Historic F5 Account

    Scope is not the problem. Tcl treats anything inside curly braces as verbatim. Enclosed strings in quotes and escape each curly brace with a backslash.

     

    tmsh_modify "ltm data-group internal /Common/snat-map records add { $::private__privateAddr { data $::public__publicAddr }}"

     

    • Fred_Slater_856's avatar
      Fred_Slater_856
      Historic F5 Account
      This wiki is not displaying what I am typing. You must add a backslash before each curly brace above.
  • Hi Fred! I've a similar questions:

    I'm modifying an iApp in order to create an irule to assign to the vs.

    the assignment is here { [iapp_conf create ltm virtual ${app}_vs \ destination [iapp_destination $::pool__addr $::pool__port] \ mask $mask \ $vs_params \ ip-protocol tcp \ mirror $mirror_action \ profiles replace-all-with { $tcp_profiles http } \ rules { iwf_test_irulebal iwf_$irulelog }] }

    the irule are very simple

    the first irule is with no variables

    tmsh::create ltm rule iwf_$irulelog {

    when HTTP_REQUEST { 
        log local0. "No variables" 
    }
    `
    
    
    }
    
    the second irule need to balance on the pool created with the iapp, so i need to write it with variable statement and not with string
    
    
    `iapp_conf create ltm rule iwf_test_irulebal {
    
    when HTTP_REQUEST { 
    
    if { [HTTP::uri] starts_with "/portal${app}_pool" } {
        use pool ${app}_pool }
    else {
        TCP::close
    }
    }
    }
    

    i've tried with \before the { but seems not works. also with ::global variable but not works.

    In a classic BIG-IP environment without iapp the use of variable in irule works. how can i use the variable in an irule created with an iapp?

    • Fred_Slater_856's avatar
      Fred_Slater_856
      Historic F5 Account

      I typically use string map.

      set app "xyz"
      
      set irule [string map " $app" {
      when HTTP_REQUEST {
        if { [HTTP::uri] starts_with "/portal_pool" } {
          use pool _pool }
        else {
          TCP::close
        }
      }
      }]
      
      iapp::conf create ltm rule iwf_test_irulebal $irule
      
    • jojo83_271212's avatar
      jojo83_271212
      Icon for Nimbostratus rankNimbostratus

      Hi Fred,

       

      I tried your suggestion but I encountered some problem with the variable "Iwf_test_irulebal".

       

      in the meantime I had solved this

       

      set :: iapp_sn $ tmsh :: app_name set :: pool_irule $ {:: iapp_sn} _pool

       

      set infile1 [open "/var/tmp/irule.tmp" "w" "0644"] puts $ infile1 "ltm rule /Common/$::iapp_sn.app/irule$::iapp_sn \ {" puts $ infile1 "app-service $ :: iapp_sn" puts $ infile1 "when HTTP_REQUEST \ {" puts $ infile1 "if \ {\ [HTTP :: uri ] starts_with \" / portal $ :: iapp_sn \ "} \ {" puts $ infile1 "use pool $ :: pool_irule }" puts $ infile1 "elseif \ {\ [HTTP :: uri ] starts_with \" / script $ :: iapp_sn \ "} \ {" puts $ infile1 "use pool $ :: pool_irule }" puts $ infile1 "else \ {" puts $ infile1 "TCP :: close" puts $ infile1 "}" puts $ infile1 "}" puts $ infile1 "}" close $ infile1

       

      tmsh :: load sys config merge check file /var/tmp/irule.tmp

       

      file delete "/var/tmp/irule.tmp"

       

      set irulevs "/Common/$::iapp_sn.app/irule$::iapp_sn"

       

      and it works.

       

      but in the end I did as suggested by crodriguez.

       

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

       

      thanks anyway Regards