{ "variables": [], "info": { "name": "AppSvcs_iApp_Workflows", "_postman_id": "5e257d05-0f8c-3924-6372-dd7143144256", "description": "Version: {{version}}", "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" }, "item": [ { "name": "1_Install_on_BIGIP", "description": "This request in this folder will install the appsvcs_integration_iapp iApp template on an F5 BIG-IP device.\n\nInput Variables:\n\nbigip_mgmt\t\tF5 BIG-IP Management Address\nbigip_token\t\tREST API Authentication Token\n\nOutput Variables:\n\nappsvcs_name\tName of the installed template", "item": [ { "name": "Install AppSvcs Template on BIG-IP", "event": [ { "listen": "test", "script": { "type": "text/javascript", "exec": [ "if(typeof postman.getGlobalVariable(\"_f5_workflow_functions\") != 'undefined') {", " eval(postman.getGlobalVariable(\"_f5_workflow_functions\"));", " ", " var check_vals = [", " {", " \"path\":\"name\",", " \"value\":\"/appsvcs_integration_v.*/i\",", " \"op\":\"regex\"", " }", " ];", " ", " var populate_vars = [", " {", " \"name\":\"appsvcs_name\",", " \"value\":\"name\"", " }", " ];", " ", " f5_check_response(check_vals);", " f5_populate_env_vars(populate_vars);", "} else {", " postman.setEnvironmentVariable('appsvcs_name', 'appsvcs_integration_v2.0.003');", "}" ] } } ], "request": { "url": " https://{{bigip_mgmt}}/mgmt/tm/sys/application/template", "method": "POST", "header": [ { "key": "Content-Type", "value": "application/json", "description": "" }, { "key": "X-F5-Auth-Token", "value": "{{bigip_token}}", "description": "" } ], "body": { "mode": "raw", "raw": "{\"name\": \"appsvcs_integration_v2.0.003\", \"actions\": [{\"name\": \"definition\", \"htmlHelp\": \"\", \"implementation\": \"# Copyright (c) 2017 F5 Networks, Inc.\\n#\\n# Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n# you may not use this file except in compliance with the License.\\n# You may obtain a copy of the License at\\n#\\n# http://www.apache.org/licenses/LICENSE-2.0\\n#\\n# Unless required by applicable law or agreed to in writing, software\\n# distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n# See the License for the specific language governing permissions and\\n# limitations under the License.\\n#\\npackage require base64\\n\\nset startTime [clock seconds]\\nset bundler_timestamp [clock format $startTime -format {%Y%m%d%H%M%S}]\\n\\nset NAME \\\"F5 Application Services Integration iApp (Community Edition)\\\"\\nset TMPLNAME \\\"appsvcs_integration_v2.0.\\\"\\nset IMPLMAJORVERSION \\\"2.0\\\"\\nset IMPLMINORVERSION \\\"003\\\"\\nset IMPLVERSION [format \\\"%s.%s\\\" $IMPLMAJORVERSION $IMPLMINORVERSION]\\nset POSTDEPLOY_DELAY 0\\n\\nif { [tmsh::get_field_value [lindex [tmsh::get_config sys scriptd log-level] 0] log-level] eq \\\"debug\\\" } {\\n set iapp__logLevel 10\\n}\\n\\n# Print a timestamped debug message to /var/tmp/scriptd.out\\n# Input: headers = TCL list of headers for the log message\\n# msg = The message to log\\n# level = Integer indicated the log level for this message\\nproc debug { headers msg level } {\\n if { $::iapp__logLevel >= $level } {\\n set systemTime [clock seconds]\\n set brackets \\\"\\\"\\n if { [llength $headers] > 0 } {\\n set brackets [format \\\"\\\\[%s\\\\]\\\" [join $headers \\\"\\\\]\\\\[\\\"]]\\n }\\n set pre [format \\\"\\\\[%s %s\\\\]\\\\[%s\\\\]%s\\\" [clock format $systemTime -format %D] [clock format $systemTime -format %H:%M:%S] $::app $brackets]\\n puts [format \\\"%s %s\\\" $pre [string map [list \\\"\\\\n\\\" \\\"\\\\n$pre \\\" ] $msg]]\\n }\\n}\\n\\n# Credit for psplit: http://wiki.tcl.tk/1499\\n# Perform the equivalent of a split on a string except protect an escaped split character in the input\\n# Input: str = the string to split\\n# seps = the charater(s) to split by\\n# Return: list $strings\\nproc psplit { str seps {protector \\\"\\\\\\\\\\\"}} {\\n set out [list]\\n set prev \\\"\\\"\\n set current \\\"\\\"\\n foreach c [split $str \\\"\\\"] {\\n if { [string first $c $seps] >= 0 } {\\n if { $prev eq $protector } {\\n set current [string range $current 0 end-1]\\n append current $c\\n } else {\\n lappend out $current\\n set current \\\"\\\"\\n }\\n set prev \\\"\\\"\\n } else {\\n append current $c\\n set prev $c\\n }\\n }\\n\\n if { $current ne \\\"\\\" } {\\n lappend out $current\\n }\\n\\n return $out\\n}\\n\\n# Figure out which type of environment we are executing in.\\n# Return: list $mode $folder $partition $routedomainid $newdeploy\\n# Modes: 1 = Standalone\\n# 2 = iWorkflow\\n# 3 = Cisco APIC\\n# 4 = VMware NSX\\nproc get_mode { } {\\n set folder [tmsh::pwd]\\n set app $tmsh::app_name\\n set partition [lindex [split $folder /] 1]\\n set newdeploy [catch {tmsh::get_config sys application service /$partition/$app.app/$app}]\\n debug [list get_mode] [format \\\"starting folder=%s partition=%s newdeploy=%s\\\" $folder $partition $newdeploy] 10\\n\\n if { ! $newdeploy } {\\n set ::asoobj [lindex [lindex [tmsh::get_config sys application service /$partition/$app.app/$app] 0] 4]\\n }\\n # Set the routedomain to the partition default-route-domain\\n if { [string tolower $::iapp__routeDomain] eq \\\"auto\\\"} {\\n set obj [tmsh::get_config auth partition $partition default-route-domain]\\n set routedomainid [tmsh::get_field_value [lindex $obj 0] default-route-domain]\\n debug [list get_mode set_route_domain] [format \\\"Using partition default-route-domain; routedomainid=%s\\\" $routedomainid] 10\\n } else {\\n set routedomainid $::iapp__routeDomain\\n debug [list get_mode set_route_domain] [format \\\"Using route domain override; routedomainid=%s\\\" $routedomainid] 10\\n }\\n\\n # Check for a mode override in $iapp__mode variable\\n if { [string tolower $::iapp__mode] ne \\\"auto\\\" } {\\n if { $::iapp__mode > 0 && $::iapp__mode < 4 } {\\n debug [list get_mode mode_override] [format \\\"Mode override detected. Setting mode to %s\\\" $::iapp__mode] 10\\n return [list $::iapp__mode $folder $partition $routedomainid $newdeploy]\\n } else {\\n error \\\"The mode override specified is invalid.\\\"\\n }\\n }\\n\\n # Check for a partition that starts with apic_ and return APIC mode (3) and RD if found\\n if { [string match -nocase \\\"apic_*\\\" $partition] || [string match -nocase \\\"apic-*\\\" $partition] } {\\n debug [list get_mode apic] \\\"partition starts with apic_, assuming APIC deployment mode (3)\\\" 10\\n set rdobjs [tmsh::get_config net route-domain \\\"/$partition/$partition\\\" id]\\n set routedomainid [tmsh::get_field_value [lindex $rdobjs 0] \\\"id\\\"]\\n debug [list get_mode apic] [format \\\"rdobjs=%s routedomainid=%s\\\" $rdobjs $routedomainid] 10\\n return [list 3 $folder $partition $routedomainid $newdeploy]\\n }\\n\\n # Check for an $app name that is formatted like this:\\n # edge-<#>_<#>_virtualserver-<#>-serviceprofile-<#>\\n # and return NSX mode (4)\\n if { [regexp -nocase {^edge-[0-9]+_[0-9]+_virtualserver-[0-9]+-serviceprofile-[0-9]+$} $::app] } {\\n debug [list get_mode nsx] \\\"app name matches NSX regexp, assuming NSX deployment mode (4)\\\" 10\\n return [list 4 $folder $partition $routedomainid $newdeploy]\\n }\\n\\n # If we get here we can safely assume that this is either a Standalone or iWorkflow mode deployment\\n # The only way we currently have to check for iWorkflow mode is to see if app_stats was sent\\n if { [info exists ::app_stats] } {\\n debug [list get_mode iworkflow] \\\"all other modes checked for and app_stats set, assuming iWorkflow deployment mode (2)\\\" 10\\n return [list 2 $folder $partition $routedomainid $newdeploy]\\n }\\n\\n # Default is Standalone mode\\n debug [list get_mode standalone] \\\"no integration vendor found, assuming Standalone deployment mode (1)\\\" 10\\n return [list 1 $folder $partition $routedomainid $newdeploy]\\n}\\n\\n# Create a specfic option command and return it\\n# Input: $debug_id, $input_var, $option_string\\n# Return: string $cmd\\nproc generic_add_option { debug_id input_var option_string custom_format replace_commas } {\\n set cmd \\\" \\\"\\n if { [string length $input_var] > 0 } {\\n if { $replace_commas == 1 } {\\n set input_var [string map {\\\",\\\" \\\" \\\"} $input_var]\\n }\\n\\n if { [string length $custom_format] > 0 } {\\n set cmd [format $custom_format $input_var]\\n } else {\\n set cmd [format \\\" $option_string \\\\\\\"%s\\\\\\\"\\\" $input_var]\\n }\\n debug [lappend debug_id generic_add_option] [format \\\"cmd=%s\\\" $cmd] 10\\n }\\n return $cmd\\n}\\n\\n# Check to see if an ip has a routedomain included.\\n# Return: 0=false; 1=true\\nproc has_routedomain { ip } {\\n return [string match *%* $ip]\\n}\\n\\n# Replace a profile within a virtual server definition while preserving the existing context\\n# Input: $obj = tmsh obj representing profiles section of the VS get_config\\n# $oldprofile = name of the profile to replace\\n# $newprofile = name of the new profile\\n# Return: string $newprofiles (string suitable for providing to replace-all-with option)\\nproc replace_profile { obj oldprofile newprofile } {\\n set profiles [tmsh::get_field_value [lindex $obj 0] \\\"profiles\\\"]\\n set newprofiles \\\" { \\\"\\n foreach profile $profiles {\\n set junk [lindex $profile 0]\\n set name [lindex $profile 1]\\n set contextobj [lindex $profile 2]\\n set context [lindex $contextobj 1]\\n if { $name eq $oldprofile } {\\n debug [list replace_profile] [format \\\"replace profile '%s' with '%s' context=%s\\\" $name $newprofile $context] 10\\n append newprofiles [format \\\"%s { context %s } \\\" $newprofile $context]\\n } else {\\n debug [list replace_profile] [format \\\"preserve profile '%s' context=%s\\\" $name $context] 10\\n append newprofiles [format \\\"%s { context %s } \\\" $name $context]\\n }\\n }\\n append newprofiles \\\" } \\\"\\n return $newprofiles\\n}\\n\\n# Look at a tmsh profile object and determine if $option is a valid profile option\\n# Input: $obj = tmsh obj to check\\n# $option = option name to look for\\n# Return: 1=Valid option; 0=Invalid option\\nproc is_valid_profile_option { obj option } {\\n debug [list is_valid_profile_option obj] [format \\\"%s\\\" $obj] 11\\n debug [list is_valid_profile_option option] [format \\\"looking for %s\\\" $option] 11\\n set found 0\\n set fdx 0\\n set fields [tmsh::get_field_names value $obj]\\n set fields2 [tmsh::get_field_names nested $obj]\\n debug [list is_valid_profile_option fields] [format \\\"%s\\\" $fields] 11\\n debug [list is_valid_profile_option fields2] [format \\\"%s\\\" $fields2] 11\\n set field_count [llength $fields]\\n while { $fdx < $field_count } {\\n set field [lindex $fields $fdx]\\n if { $field == $option } {\\n return 1\\n }\\n incr fdx\\n }\\n set field_count [llength $fields2]\\n set fdx 0\\n while { $fdx < $field_count } {\\n set field [lindex $fields2 $fdx]\\n if { $field == $option } {\\n return 1\\n }\\n incr fdx\\n }\\n return 0\\n}\\n\\n# Process a string in the format key1=val1[;keyX=valX] and return an array\\n# Input: $string = string to process\\n# Return: array { key1 {val1} ... keyX{valX}}\\nproc process_kvp_string { string } {\\n debug [list process_kvp_string] \\\"processing string: $string\\\" 10\\n set pairs [psplit $string \\\";\\\"]\\n array set ret {}\\n foreach pair $pairs {\\n set key [lindex [split $pair =] 0]\\n set val [lindex [split $pair =] 1]\\n set ret($key) $val\\n debug [list process_kvp_string] \\\"pair=$pair key=$key val=$val\\\" 10\\n }\\n return [array get ret]\\n}\\n\\n# Create an object name\\n# Input: $append = string to append\\n# Return: $string\\nproc create_obj_name { append } {\\n return [format \\\"%s/%s_%s\\\" $::app_path $::app $append]\\n}\\n\\n# Safely change a variable to a new value. Updates the var value and modifies the ASO with the new value\\n# Input: $name = name of variable\\n# $value = new value of the variable\\n# Return: none\\nproc change_var { name value } {\\n debug [list change_var] \\\"updating variable $name to $value (executes post-deployment)\\\" 10\\n set varcmd [create_escaped_tmsh [format \\\"tmsh::modify sys application service %s/%s variables modify \\\\{ %s \\\\{ value \\\\\\\"%s\\\\\\\" \\\\} \\\\}\\\" $::app_path $::app $name $value]]\\n debug [list change_var tmsh_modify_deferred] $varcmd 1\\n lappend ::postfinal_deferred_cmds $varcmd\\n set [subst ::$name] $value\\n set ::aso_config($name) $value\\n return\\n}\\n\\n# Check to see if an incoming variable is different than whats stored in the ASO.\\n# Input: $name = name of variable\\n# Return: 1=value is different; 0=value not different OR not a redeploy\\nproc is_new_value { name } {\\n if { $::newdeploy } {\\n return 0\\n }\\n set varvalue [get_var $name]\\n debug [list is_new_value] [format \\\"name=%s asovalue=%s varvalue=%s\\\" $name $varvalue [set [subst ::$name]]] 10\\n if { [set [subst ::$name]] == $varvalue } {\\n return 0\\n }\\n return 1\\n}\\n\\n# Get the variable value in the ASO.\\n# Input: $name = name of variable\\n# $orig = return the original value, not the runtime updated one\\n# Return: $string = value of variable\\nproc get_var { name { orig 0 }} {\\n if { $::newdeploy == 1} {\\n return \\\"\\\"\\n }\\n debug [list get_var] [format \\\"start name=%s\\\" $name] 10\\n\\n if { $orig == 0 && [info exists ::aso_config($name)] } {\\n set varvalue $::aso_config($name)\\n debug [list get_var] [format \\\"name=%s value=%s\\\" $name $varvalue] 10\\n return $varvalue\\n }\\n\\n if { $orig == 1 && [info exists ::aso_config_orig($name)] } {\\n set varvalue $::aso_config_orig($name)\\n debug [list get_var original] [format \\\"name=%s value=%s\\\" $name $varvalue] 10\\n return $varvalue\\n }\\n return \\\"\\\"\\n}\\n\\n# Safely handle the removal of a virtual server option on redeployment\\n# Input: $name = name of variable\\n# $checkvalue = the string that disables the option\\n# $option = TMSH name of the option\\n# $module = the BIG-IP module that enables the option\\n# Return: 1=Option removed; 0=no action taken\\nproc handle_opt_remove_on_redeploy { name checkvalue option module } {\\n if { ! $::redeploy || $::pool__addr eq \\\"255.255.255.254\\\" } {\\n debug [list handle_opt_remove_on_redeploy $name] \\\"not a redeployment, skipping\\\" 10\\n return 0\\n }\\n\\n if { ! [is_provisioned $module] } {\\n debug [list handle_opt_remove_on_redeploy $name] [format \\\"%s not provisioned, skipping\\\" $module] 10\\n return 0\\n }\\n\\n set vsname [get_var vs__Name 1]\\n set vsobj [lindex [tmsh::get_config ltm virtual $::app_path/$vsname all-properties] 0]\\n if { [is_valid_profile_option $vsobj $option] == 0 } {\\n debug [list handle_opt_remove_on_redeploy $name] [format \\\"%s not available, skipping\\\" $option] 10\\n return 0\\n }\\n\\n if { [set [subst ::$name]] == $checkvalue && \\\\\\n [is_new_value $name] && \\\\\\n $::redeploy } {\\n debug [list handle_opt_remove_on_redeploy] [format \\\"%s %s on redeploy, setting %s to none\\\" $name $checkvalue $option] 10\\n set cmd [format \\\"ltm virtual %s/%s %s none\\\" $::app_path $vsname $option]\\n debug [list handle_opt_remove_on_redeploy tmsh_modify] $cmd 1\\n tmsh::modify $cmd\\n return 1\\n }\\n return 0\\n}\\n\\n# Check provisioning cache for whether a specified module is provisioned and at what levels\\n# Adapted from original code including the F5 iApp TCL helper library\\n# Input: $module = name of the module\\n# Output: $level = integer representation of the provisioning level. See levels array below\\nproc is_provisioned { module } {\\n array set levels {\\n none 0\\n minimum 1\\n nominal 2\\n dedicated 3\\n }\\n\\n if { [info exists ::__provision_cache($module)] } {\\n debug [list is_provisioned cache_hit] \\\"$module $::__provision_cache($module)\\\" 10\\n return [expr { $levels($::__provision_cache($module)) >= 1 }]\\n } else {\\n debug [list is_provisioned cache_miss] \\\"$module\\\" 10\\n return -1\\n }\\n}\\n\\n# Load provisioning cache with module provisioning levels\\n# Adapted from original code including the F5 iApp TCL helper library\\nproc load_provisioned { } {\\n array set levels {\\n none 0\\n minimum 1\\n nominal 2\\n dedicated 3\\n }\\n set obj [tmsh::get_config sys provision]\\n foreach mod $obj {\\n set modname [lindex $mod 2]\\n set modlevel [lindex $mod 3]\\n if { [llength $modlevel] == 2 } {\\n set modlevel [lindex $modlevel 1]\\n } else {\\n set modlevel none\\n }\\n set ::__provision_cache($modname) $modlevel\\n debug [list load_provisioned cache_set] \\\"$modname $modlevel\\\" 10\\n }\\n}\\n\\n# Consume an APL table and return a list containing the values of the var specified in $key\\n# Input: $table = the raw APL table\\n# $key = the name of the variable to add to the return list\\n# Output: $retlist = A list of strings\\nproc single_column_table_to_list { table key } {\\n set retlist {}\\n foreach row $table {\\n array unset column\\n\\n # extract the iApp table data - borrowed from f5.lbaas.tmpl\\n foreach column_data [lrange [split [join $row] \\\"\\\\n\\\"] 1 end-1] {\\n set name [lindex $column_data 0]\\n set column($name) [lrange $column_data 1 end]\\n }\\n if { [info exists column($key)] && [string length $column($key)] > 0 } {\\n lappend retlist \\\"$column($key)\\\"\\n }\\n\\n }\\n return $retlist\\n}\\n\\n# Process a string in the format