Creating an iApp Template from a Working Config¶
This is a description of how to build an iApp Template from a working
config defined in bigip.conf. This is just one of many ways of going
about writing an iApp Template, but it is one that has been used
successfully for a number of iApps. This process may not be
appropriate for all templates. It is fairly tedious to do it this way,
but it can be very helpful for complicated configs and it can be
useful is you don’t know how to create the config that you want using
TMSH. It also has the benefit of starting with something that works
and that you can compare against easily. This process is almost a
requirement for configs involving the APM module.
Preparing the Configuration¶
1. To begin with, start with a clean BIG-IP. You don’t want extra
objects on there to confuse the situation. It is a really good idea to
save a copy of the file /config/bigip.conf when the system is clean
and has no config on it yet. You can use this later to help determine
what is basic to this file that is not a part of your config.
a. If you can’t get your system to a clean state, make a copy of your
/config/bigip.conf before you start so that you have a complete list
of those objects that you don’t want to include in your iApp
template.
2. Build the solution that you eventually want the template to create
manually through the GUI.
3. Completely test the solution to ensure that you are starting with
the very best configuration possible.
4. Backup the configuration by making a copy of the file
/config/bigip.conf. Copy this backup off the BIG-IP for safe keeping.
Getting the Template Started¶
1. Create a new template and open if for editing in whichever way
works best for you. (If you need some help with this step, see iApp
Lab 1 - Hello World.)
2. In the Presentation section, start with just a basic message
telling the user the name of your template. You don’t have any options
yet, so the only thing the user will be able to do is submit the
template. That is fine for now.
3. In the Implementation section, we are going to start with the
contents of the file /config/bigip.conf. Copy the contents of
bigip.conf and paste them into the implementation section of your
template. This is not going to work as first. This is just the
starting point. We have a whole process to go through to turn this
into working code.
Converting the Config to Working Template Code¶
There are a whole series of steps to go through to transform the
config that you just pasted into the implementation section. This
discussion cannot cover what to do in every situation, but it should
provide good advice for how to do most things.
Cleanup the Config¶
The file bigip.conf contains the config that you have created, but
just because something is in bigip.conf, doesn’t meant that you want
to try to create it in your template. There are boiler-plate objects
in there and also objects that get created automatically when create
other objects. You don’t want to try to create either of these things
in your template. It will result in errors. The following is a good
start to getting rid of the extra cruft.
1. Remove any extraneous config objects. This is where the bigip.conf
from when the system was clean (or from when you started) comes in
handy. If you open that file, you will see that it isn’t blank. There
are some objects defined in there even when the system is fresh and
new. You don’t need to recreate those objects. Remove their reference
from your Implementation section.
2. Remove all of the ‘/ltm node’ objects. These are created
automatically by the system when the pools are created.
There may be other objects that still don’t belong, but we will have
to find them later.
Making the Initial Conversion¶
Now we edit the contents of the Implementation section to turn it into
actual Tcl code. Your implementation section contains a series of
object definitions of the form
<TMSH Path> /<Partition Path>/<Object Name> {<Object Definition> }
For example,
ltm pool /Common/my_pool {
members {
/Common/10.133.21.103:http {
address 10.133.21.103
}
}
monitor /Common/my_http_monitor
slow-ramp-time 300
}
This is going to have to be processed to turn it into usable code.
1. Remove the Partition Path. You don’t want to specify this in
templates in most cases. The iApp system will automatically place the
objects in the correct path. If you created your config in the Common
partition, then the partition path is ‘/Common/’. You can remove all
of them using a global search-and-replace.
2. Remove the outer curly braces from around the Object Definition,
without removing any internal curly braces. Now you should have
something that look more like this.
<TMSH Path> <Object Name> <Object Definition>
For example,
ltm pool my_pool
members {
10.133.21.103:http {
address 10.133.21.103
}
}
monitor my_http_monitor
slow-ramp-time 300
3. Now, encase each object inside a call to tmsh::create. It should
look like this
tmsh::create {
ltm pool my_pool
members {
10.133.21.103:http {
address 10.133.21.103
}
}
monitor my_http_monitor
slow-ramp-time 300
}
4. Replace every instance of ‘members {‘ with ‘members
replace-all-with {‘
5. Replace every instance of ‘profiles {‘ with ‘profiles
replace-all-with {‘
6. Replace every instance of ‘persist {‘ with ‘persist
replace-all-with {‘
7. If you have GTM objects, replace every instance of ‘pools {‘ with
‘pools replace-all-with {‘
Adding Escape Characters¶
If your config contains iRules, you may need to escape some special
characters to get this to run correctly.
1. inside the iRule definition,
- Replace all instances of $ with \$
- Replace all instances of [ with \[
- Replace all instances of ] with \]
- Replace all instances of ” with "
This will keep the Tcl interpreter from trying to do variable
substitution or trying to run procs that don’t exist.
Testing the Conversion¶
In many cases, this will work now. In some cases, there are further
edits that need to be made. You will need to test the template and see
if it is working yet, and fix any problems that may arise.
1. Now is a good time to save your template. If you are editing
outside of the BIG-IP, import your template back in.
2. Before you run your template, you want to remove your original
config. The easiest way to do this is to replace the file
/config/bigip.conf with the one you saved when your system was clean.
Then run the command ‘tmsh load sys config’ from the command line.
3. Now you want to run your template and test to see that it works. If
you have errors, correct them before continuing.
a. One common problem that you might run into is that some object
types will have fields in them that are auto-generated by the system
when the object is created. These fields should be removed from your
Implementation section. You will be able to find these because you
will get an error message complaining about unknown fields when you
try to run the template. A good example of this is the ‘revision’ or
‘cache-path’ fields in APM policy objects.
policy customization-group /Common/atest_citrix_apm_Connectivity_customization {
app-service /Common/atest.app/atest
cache-path /config/filestore/files_d/Common_d/customization_group_d/:Common:atest_citrix_apm_Connectivity_customization_1
revision 1
type secure-access-client
}
If you try to set the revision field with a TMSH create command, for
example, you get the following error:
Command failed: tmsh::create apm policy customization-group /Common/atest_citrix_apm_Connectivity_customization { type secure-access-client revision 4 } "revision" read-only property
4. Make sure that your template is creating the config that you want
by comparing the new /config/bigip.conf with the one that you saved
containing your original config. They should be the same, except that
- The objects get created inside the template’s folder.
b. Each object now contains a new field, app-service, which specifies
which iApp Application Service owns the object.
Making Your Template Dynamic¶
At this point in the process, your template runs correctly, but it
always makes the same static config. In most cases, this is not the
desired final product. In most cases, you want to give your user the
ability to make choices about the config. This is done by adding
content to the Presentation section to gather the information, and
then using that input in the Implementation section to make choices or
fill in content. In some cases, you will only want a few inputs in the
Presentation section, while in others, your Presentation section might
get very involved. This discussion cannot cover every possible case,
but here are some things that you may want to do to your template.
Personalizing Object Names¶
Not happy with your original object names? Now is a good time to edit
them to better fit the image you want to present. You can also make
the names dynamicly generated, perhaps by beginning them all with the
name of the iApp Application Service that owns them. This is how you
do that. For each object instance,
1. Set the object name as a combination of the app name and the
original object name, like this:
set object_name [format "%s_%s" $tmsh::app_name original_object_name]
2. Then replace the object name in the tmsh::create statement with the
new one variable that you just set, like this:
set object_name [format "%s_%s" $tmsh::app_name my_pool]
tmsh::create {
ltm pool $object_name
members replace-all-with {
10.133.21.103:http {
address 10.133.21.103
}
}
monitor my_http_monitor
slow-ramp-time 300
}
Inserting User Input¶
Let’s say that you want the user to be able to select the load
balancing method and the monitor on the pool that you are creating.
Here is how you do that, using the example from above.
1. In the Presentation section, add two choice elements to collect the
information that you want. For example,
section pool_choices {
choice monitor_name display "xlarge" tcl {
tmsh::run_proc f5.app_utils:get_ltm_monitors_filter http
}
choice lb_method_choice default "round-robin" display "xlarge" {
"Dynamic Ratio (member)" => "dynamic-ratio-member",
"Dynamic Ratio (node)" => "dynamic-ratio-node",
"Fastest (application)" => "fastest-app-response",
"Fastest (node)" => "fastest-node",
"Least Connections (member)" => "least-connections-member",
"Least Connections (node)" => "least-connections-node",
"Least Sessions" => "least-sessions",
"Observed (member)" => "observed-member",
"Observed (node)" => "observed-node",
"Predictive (member)" => "predictive-member",
"Predictive (node)" => "predictive-node",
"Round Robin" => "round-robin",
"Ratio (member)" => "ratio-member",
"Ratio (node)" => "ratio-node",
"Ratio (session)" => "ratio-session",
"Ratio Least Connections (member)" => "ratio-least-connections-memeber",
"Ratio Least Connections (node)" => "ratio-least-connections-node",
"Weighted Least Connections (member)" => "weighted-least-connections-member",
"Weighted Least Connections (node)" => "weighted-least-connections-node"
}
}
2. In the implementation section, insert the result, like this:
set object_name [format "%s_%s" $tmsh::app_name my_pool]
tmsh::create {
ltm pool $object_name
members replace-all-with {
10.133.21.103:http {
address 10.133.21.103
}
}
monitor $::pool_choices__monitor_name
slow-ramp-time 300
load-balancing-mode $::pool_choices__lb_method_choice
}
Letting the User Define the Pool Members¶
In almost every case, the pools’ members need to be selected
dynamically by the user when they run the template. Here is an example
of how to do that.
1. In the Presentation section, add a table to gather the pool member
choices. For example,
section pool_choices {
lb_method lb_method_choice
table servers {
string addr required validator "IpAddress"
string port default "80" required validator "PortNumber" display "small"
string connection_limit default "0" required validator "NonNegativeNumber" display "small"
optional ( lb_method_choice == "ratio-member" ||
lb_method_choice == "ratio-node" ||
lb_method_choice == "ratio-session" ||
lb_method_choice == "ratio-least-connections-memeber" ||
lb_method_choice == "ratio-least-connections-node" ||
lb_method_choice == "dynamic-ratio-member" ||
lb_method_choice == "dynamic-ratio-node" ) {
string ratio default "1" validator "NonNegativeNumber" display "small"
}
}
choice monitor_name display "xlarge" tcl {
tmsh::run_proc f5.app_utils:get_ltm_monitors_filter http
}
2. in the Implementation section, process the results of that input,
like this:
set servers $::pool_choices__servers
if { $servers == "" } {
set members action "members none"
} else {
set members \{
foreach server $servers {
append members [tmsh::get_field_value $server addr]
append members ":"
append members [tmsh::get_field_value $server port]
append members " \{ connection-limit "
append members [tmsh::get_field_value $server connection_limit]
if { [tmsh::run_proc f5.app_utils:is_lb_method_ratio $lb_method] } {
append members " ratio "
append members [tmsh::get_field_value $server ratio]
}
append members " \}"
append members " "
}
append members \}
set members action "members replace-all_with $members"
}
set object_name [format "%s_%s" $tmsh::app_name my_pool]
tmsh::create {
ltm pool $object_name
$members_action
monitor $::pool_choices__monitor_name
slow-ramp-time 300
load-balancing-mode $::pool_choices__lb_method_choice
}
Other Common Things To Change¶
The number of ways that you can make your config dynamic are endless.
It just depends on what you want to present as options to your user.
You want to make your template flexible enough that it is useful for
all of the common ways that you or your user want to use it to deploy
iApp Application Services. We’ll close this discussion with a short,
non-exhaustive list of common things that you might want to make
dynamic.
1. Allow the user set the IP address and port values for virtual
servers.
2. Allow the user choose SSL Keys and Certificates.
3. Allow the user define their own monitor send and receive strings.
4. Give the user choices for how to optimize HTTP traffic for their
environment.
5. Give the user choices about what VLANs the virtual servers should
answer on.
6. Etc…
—-
The BIG-IP API Reference documentation contains community-contributed content. F5 does not monitor or control community code contributions. We make no guarantees or warranties regarding the available code, and it may contain errors, defects, bugs, inaccuracies, or security vulnerabilities. Your access to and use of any code available in the BIG-IP API reference guides is solely at your own risk.