From 330a7e9c55d7c970349185e931b8ede91cc52ac4 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Fri, 16 May 2025 00:36:23 +1000 Subject: [PATCH] punk::netbox::man update -limit and -MAXRESULTS --- src/modules/punk/netbox-999999.0a1.0.tm | 13 +- src/modules/punk/netbox/man-999999.0a1.0.tm | 169 ++++++++++++++---- .../modules/punk/netbox-0.1.0.tm | 13 +- .../modules/punk/netbox/man-0.1.0.tm | 169 ++++++++++++++---- 4 files changed, 280 insertions(+), 84 deletions(-) diff --git a/src/modules/punk/netbox-999999.0a1.0.tm b/src/modules/punk/netbox-999999.0a1.0.tm index cef961c6..1d88ea74 100644 --- a/src/modules/punk/netbox-999999.0a1.0.tm +++ b/src/modules/punk/netbox-999999.0a1.0.tm @@ -1402,7 +1402,7 @@ tcl::namespace::eval punk::netbox::ipam { @opts }\ [set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\ - [set ::punk::netbox::argdoc::_RETURN_DICT]\ + [set ::punk::netbox::argdoc::_RETURN_LIST]\ { @values -min 1 -max 2 id -type integer -help\ @@ -1412,13 +1412,19 @@ tcl::namespace::eval punk::netbox::ipam { If empty create a single IP with default values. (next available IP in prefix) - Create 2 IPs: + e.g Create 2 IPs: [ {"description": "ip1"}, - {"description": "ip2"} + { + "description": "ip2", + "tenant": 5, + "dns_name": "test.intx.com.au" + } ] + NOTE1: tenant is the tenant_id (why?) NOTE: This always uses next available IPs. To create a specific IP, use api/ipam/ip-addresses endpoint. + The returned json is just an object if one address created, but a list if multiple. :/ @@ -1642,7 +1648,6 @@ tcl::namespace::eval punk::netbox::tenancy { -tag -type string -tag__n -type string }\ - [set ::punk::netbox::argdoc::_tenant_options]\ [set ::punk::netbox::argdoc::_contact_options]\ { }\ diff --git a/src/modules/punk/netbox/man-999999.0a1.0.tm b/src/modules/punk/netbox/man-999999.0a1.0.tm index 7d88468f..db1110e9 100644 --- a/src/modules/punk/netbox/man-999999.0a1.0.tm +++ b/src/modules/punk/netbox/man-999999.0a1.0.tm @@ -137,6 +137,7 @@ tcl::namespace::eval punk::netbox::man::prefixes { lappend PUNKARGS [::list\ [punk::args::resolved_def -antiglobs {apicontextid @leaders @values -RETURN} -override {@id {-id "::punk::netbox::man::prefixes list"}} ::punk::netbox::ipam::prefixes_list]\ {-RETURN -default table -choices {table tableobject list}}\ + {-MAXRESULTS -type integer -default -1}\ {@values -min 0 -max 0}\ ] @@ -145,12 +146,15 @@ tcl::namespace::eval punk::netbox::man::prefixes { set argd [punk::args::parse $args withid "::punk::netbox::man::prefixes list"] set token tclread ;#todo - set next "" + set urlnext "" set requests_allowed 1000 ;#review set resultlist [::list] set opts [dict get $argd opts] set vals [dict get $argd values] set multis [dict get $argd multis] + set maxresults [dict get $opts -MAXRESULTS] + set initial_pagelimit [dict get $opts -limit] + set opts [dict remove $opts -MAXRESULTS] set outer_return [dict get $opts -RETURN] set opts [dict remove $opts -RETURN] ;#opts from punk::args::parse is a dict (no dup keys) - can use 'dict remove' safely #we can't just pass through 'multi' opts even if only one was supplied - list level is wrong @@ -166,24 +170,30 @@ tcl::namespace::eval punk::netbox::man::prefixes { } #Now opts is a list with possible repeated options! (for flags that have -multiple true) - while {$next ne "null"} { - if {$next ni [::list "" null]} { - set plist [punk::netbox::man::uri_get_querystring_as_keyval_list $next] - #don't use any dict write operations on plist/nextopts - can destroy dup keys - set p_offset [lsearch -stride 2 $plist offset] ;#only search in 'key' positions - for -offset we are only expecting/allowing a single entry - if {$p_offset != -1} { - lappend nextopts -offset [lindex $plist $p_offset+1] - } - set p_limit [lsearch -stride 2 $plist limit] - if {$p_limit != -1} { - lappend nextopts -limit [lindex $plist $p_limit+1] + if {$maxresults == -1} { + set maxresults $initial_pagelimit + } + if {$maxresults < $initial_pagelimit} { + punk::netbox::man::system::dupkeylist_setfirst nextopts -limit $maxresults + } + set to_go [expr {$maxresults - [llength $resultlist]}] + while {$urlnext ne "null"} { + if {$urlnext ne ""} { + set urlnext_params [punk::netbox::man::uri_get_querystring_as_keyval_list $urlnext] + if {[punk::netbox::man::system::dupkeylist_getfirst $nextopts -limit] > $to_go} { + punk::netbox::man::system::dupkeylist_setfirst urlnext_params limit $to_go } + #sync to -limit,-offset from the url's limit, offset values + punk::netbox::man::system::optionlistvar_sync_from_urlparams nextopts $urlnext_params } - puts "-->next:$next nextopts:$nextopts vals:$vals" + puts "-->next:$urlnext nextopts:$nextopts vals:$vals" set resultd [punk::netbox::ipam::prefixes_list $token {*}$nextopts -RETURN dict {*}$vals] - set next [dict get $resultd next] + set urlnext [dict get $resultd next] set batch [dict get $resultd results] lappend resultlist {*}$batch + + set to_go [expr {$maxresults - [llength $resultlist]}] + if {$to_go <= 0} {break} incr requests_allowed -1 if {$requests_allowed < 1} {break} } @@ -252,8 +262,6 @@ tcl::namespace::eval punk::netbox::man::prefixes { set argd [punk::args::parse $args withid "::punk::netbox::man::prefixes available-ips_list"] set token tclread ;#todo - set next "" - set requests_allowed 1000 ;#review set resultlist [::list] set opts [dict get $argd opts] set valuedict [dict get $argd values] @@ -274,17 +282,26 @@ tcl::namespace::eval punk::netbox::man::prefixes { } #Now opts is a list with possible repeated options! (for flags that have -multiple true) - #No paging available at endpoint ipam/prefixes/available-ips - but we can still use limit (but offset doesn't seem to work + #No paging available at endpoint ipam/prefixes/available-ips - but we can still use limit (but offset doesn't seem to work) + #REVIEW - no way to know if *all* available in a prefix were returned - could/should? have been limited by server setting + #Especially in an ipv6 context - we're *very* unlikely to want to try to get all! (even for a /16 ipv4 it's probably not a very sensible query) + #Default netbox server limit seems to be 1000? review + #setting -limit 0 seems to allow this to be overridden - giving results bounded only by size of the prefix? set resultlist [punk::netbox::ipam::prefixes_available-ips_list $token {*}$nextopts -RETURN list {*}$vals] if {$outer_return in {table tableobject}} { package require textblock set t [textblock::list_as_table -return tableobject -colheaders {address family vrf}] foreach ip $resultlist { + if {[dict exists $ip vrf id]} { + set vrfinfo "[dict get $ip vrf id]: [dict get $ip vrf name]" + } else { + set vrfinfo "-" + } set r [::list\ [dict get $ip address]\ [dict get $ip family]\ - "[dict get $ip vrf id]: [dict get $ip vrf name]"\ + $vrfinfo\ ] $t add_row $r } @@ -334,7 +351,8 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { lappend PUNKARGS [::list\ [punk::args::resolved_def -antiglobs {apicontextid @leaders @values -RETURN} -override {@id {-id "::punk::netbox::man::ip-addresses list"}} ::punk::netbox::ipam::ip-addresses_list]\ - {-RETURN -default table -choices {table tableobject list}}\ + {-RETURN -default table -choices {table tableobject list linelist}}\ + {-MAXRESULTS -type integer -default -1}\ {@values -min 0 -max 0}\ ] @@ -343,14 +361,17 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { set argd [punk::args::parse $args withid "::punk::netbox::man::ip-addresses list"] set token tclread ;#todo - set next "" - set requests_allowed 1000 ;#review + set urlnext "" + set requests_allowed 1000 ;#Sanity check - consider making an option - review set resultlist [::list] set opts [dict get $argd opts] set vals [dict get $argd values] set multis [dict get $argd multis] set outer_return [dict get $opts -RETURN] - set opts [dict remove $opts -RETURN] ;#opts from punk::args::parse is a dict (no dup keys) - can use 'dict remove' safely + set opts [dict remove $opts -RETURN] ;#opts from punk::args::parse is a dict (no dup keys) - can use 'dict remove' safely + set maxresults [dict get $opts -MAXRESULTS] + set opts [dict remove $opts -MAXRESULTS] + set initial_pagelimit [dict get $opts -limit] #we can't just pass through 'multi' opts even if only one was supplied - list level is wrong set nextopts [::list] dict for {opt val} $opts { @@ -364,27 +385,33 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { } #Now opts is a list with possible repeated options! (for flags that have -multiple true) - while {$next ne "null"} { - if {$next ni [::list "" null]} { - set plist [punk::netbox::man::uri_get_querystring_as_keyval_list $next] - #don't use any dict write operations on plist/nextopts - can destroy dup keys - set p_offset [lsearch -stride 2 $plist offset] ;#only search in 'key' positions - for -offset we are only expecting/allowing a single entry - if {$p_offset != -1} { - lappend nextopts -offset [lindex $plist $p_offset+1] - } - set p_limit [lsearch -stride 2 $plist limit] - if {$p_limit != -1} { - lappend nextopts -limit [lindex $plist $p_limit+1] + if {$maxresults == -1} { + set maxresults $initial_pagelimit + } + if {$maxresults < $initial_pagelimit} { + punk::netbox::man::system::dupkeylist_setfirst nextopts -limit $maxresults + } + set to_go [expr {$maxresults - [llength $resultlist]}] + while {$urlnext ne "null"} { + if {$urlnext ne ""} { + set urlnext_params [punk::netbox::man::uri_get_querystring_as_keyval_list $urlnext] + if {[punk::netbox::man::system::dupkeylist_getfirst $nextopts -limit] > $to_go} { + punk::netbox::man::system::dupkeylist_setfirst urlnext_params limit $to_go } + punk::netbox::man::system::optionlistvar_sync_from_urlparams nextopts $urlnext_params } - puts "-->next:$next nextopts:$nextopts vals:$vals" + puts "-->next:$urlnext nextopts:$nextopts vals:$vals" set resultd [punk::netbox::ipam::ip-addresses_list $token {*}$nextopts -RETURN dict {*}$vals] - set next [dict get $resultd next] + set urlnext [dict get $resultd next] set batch [dict get $resultd results] lappend resultlist {*}$batch + + set to_go [expr {$maxresults - [llength $resultlist]}] + if {$to_go <= 0} {break} incr requests_allowed -1 if {$requests_allowed < 1} {break} } + if {$outer_return in {table tableobject}} { package require textblock set t [textblock::list_as_table -return tableobject -colheaders {id address family vrf_id tenant status assigned_object_type deviceinfo dns_name description}] @@ -407,11 +434,16 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { set deviceinfo - } } + if {[dict exists $ip vrf id]} { + set vrfinfo "[dict get $ip vrf id]: [dict get $ip vrf name]" + } else { + set vrfinfo "-" + } set r [::list\ [dict get $ip id]\ [dict get $ip address]\ [dict get $ip family label]\ - [dict get $ip vrf id]\ + $vrfinfo\ $tenant\ [dict get $ip status value]\ [dict get $ip assigned_object_type]\ @@ -431,14 +463,75 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { tableobject { return $t } + linelist { + set ret "" + foreach r $resultlist { + append ret $r \n + } + return $ret + } + default { + return $resultlist + } } - return $resultlist - #return [showdict $resultd] } } +tcl::namespace::eval punk::netbox::man::system { + + #update/add specific members of optionlistvar params in dashed -option format from urlparams in undashed format + #members: offset,limit -> -offset,-limit + #Must support duplicate keys in either *list* + #i.e don't use any dict write operations on paramlistvar - can destroy dup keys + proc optionlistvar_sync_from_urlparams {optionlistvar urlparams} { + upvar 1 $optionlistvar optionlist + + set posn_url_offset [lsearch -stride 2 $urlparams offset] ;#only search in 'key' positions - for offset,limit we are only expecting/allowing a single entry + set posn_option_offset [lsearch -stride 2 $optionlist -offset] + if {$posn_url_offset != -1} { + if {$posn_option_offset != -1} { + lset optionlist $posn_option_offset+1 [lindex $urlparams $posn_url_offset+1] + } else { + lappend optionlist -offset [lindex $urlparams $posn_url_offset+1] + } + } else { + set optionlist [lremove $optionlist $posn_option_offset $posn_option_offset+1] + } + + set posn_url_limit [lsearch -stride 2 $urlparams limit] + set posn_option_limit [lsearch -stride 2 $optionlist -limit] + if {$posn_url_limit != -1} { + if {$posn_option_limit != -1} { + lset optionlist $posn_option_limit+1 [lindex $urlparams $posn_url_limit+1] + } else { + lappend optionlist -limit [lindex $urlparams $posn_url_limit+1] + } + } else { + set optionlist [lremove $optionlist $posn_option_limit $posn_option_limit+1] + } + return + } + + #single level dict-like list with possible duplicate keys + #These functions should be used for keys which we *dont'* expect to be duplicates + #functions are names getfirst,setfirst to make the behaviour explicit/apparent + proc dupkeylist_getfirst {dupkeylist topkey} { + set posn [lsearch -stride 2 $dupkeylist $topkey] + if {$posn == -1} {return} + return [lindex $dupkeylist $posn+1] + } + proc dupkeylist_setfirst {dupkeylistvar topkey val} { + upvar 1 $dupkeylistvar dupkeylist + set posn [lsearch -stride 2 $dupkeylist $topkey] + if {$posn == -1} { + lappend dupkeylist $topkey $val + return $dupkeylist + } + lset dupkeylist $posn+1 $val + } +} # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # Secondary API namespace diff --git a/src/vfs/_vfscommon.vfs/modules/punk/netbox-0.1.0.tm b/src/vfs/_vfscommon.vfs/modules/punk/netbox-0.1.0.tm index 020bb7a9..7a072de4 100644 --- a/src/vfs/_vfscommon.vfs/modules/punk/netbox-0.1.0.tm +++ b/src/vfs/_vfscommon.vfs/modules/punk/netbox-0.1.0.tm @@ -1402,7 +1402,7 @@ tcl::namespace::eval punk::netbox::ipam { @opts }\ [set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\ - [set ::punk::netbox::argdoc::_RETURN_DICT]\ + [set ::punk::netbox::argdoc::_RETURN_LIST]\ { @values -min 1 -max 2 id -type integer -help\ @@ -1412,13 +1412,19 @@ tcl::namespace::eval punk::netbox::ipam { If empty create a single IP with default values. (next available IP in prefix) - Create 2 IPs: + e.g Create 2 IPs: [ {"description": "ip1"}, - {"description": "ip2"} + { + "description": "ip2", + "tenant": 5, + "dns_name": "test.intx.com.au" + } ] + NOTE1: tenant is the tenant_id (why?) NOTE: This always uses next available IPs. To create a specific IP, use api/ipam/ip-addresses endpoint. + The returned json is just an object if one address created, but a list if multiple. :/ @@ -1642,7 +1648,6 @@ tcl::namespace::eval punk::netbox::tenancy { -tag -type string -tag__n -type string }\ - [set ::punk::netbox::argdoc::_tenant_options]\ [set ::punk::netbox::argdoc::_contact_options]\ { }\ diff --git a/src/vfs/_vfscommon.vfs/modules/punk/netbox/man-0.1.0.tm b/src/vfs/_vfscommon.vfs/modules/punk/netbox/man-0.1.0.tm index b4b73b76..23e7264a 100644 --- a/src/vfs/_vfscommon.vfs/modules/punk/netbox/man-0.1.0.tm +++ b/src/vfs/_vfscommon.vfs/modules/punk/netbox/man-0.1.0.tm @@ -137,6 +137,7 @@ tcl::namespace::eval punk::netbox::man::prefixes { lappend PUNKARGS [::list\ [punk::args::resolved_def -antiglobs {apicontextid @leaders @values -RETURN} -override {@id {-id "::punk::netbox::man::prefixes list"}} ::punk::netbox::ipam::prefixes_list]\ {-RETURN -default table -choices {table tableobject list}}\ + {-MAXRESULTS -type integer -default -1}\ {@values -min 0 -max 0}\ ] @@ -145,12 +146,15 @@ tcl::namespace::eval punk::netbox::man::prefixes { set argd [punk::args::parse $args withid "::punk::netbox::man::prefixes list"] set token tclread ;#todo - set next "" + set urlnext "" set requests_allowed 1000 ;#review set resultlist [::list] set opts [dict get $argd opts] set vals [dict get $argd values] set multis [dict get $argd multis] + set maxresults [dict get $opts -MAXRESULTS] + set initial_pagelimit [dict get $opts -limit] + set opts [dict remove $opts -MAXRESULTS] set outer_return [dict get $opts -RETURN] set opts [dict remove $opts -RETURN] ;#opts from punk::args::parse is a dict (no dup keys) - can use 'dict remove' safely #we can't just pass through 'multi' opts even if only one was supplied - list level is wrong @@ -166,24 +170,30 @@ tcl::namespace::eval punk::netbox::man::prefixes { } #Now opts is a list with possible repeated options! (for flags that have -multiple true) - while {$next ne "null"} { - if {$next ni [::list "" null]} { - set plist [punk::netbox::man::uri_get_querystring_as_keyval_list $next] - #don't use any dict write operations on plist/nextopts - can destroy dup keys - set p_offset [lsearch -stride 2 $plist offset] ;#only search in 'key' positions - for -offset we are only expecting/allowing a single entry - if {$p_offset != -1} { - lappend nextopts -offset [lindex $plist $p_offset+1] - } - set p_limit [lsearch -stride 2 $plist limit] - if {$p_limit != -1} { - lappend nextopts -limit [lindex $plist $p_limit+1] + if {$maxresults == -1} { + set maxresults $initial_pagelimit + } + if {$maxresults < $initial_pagelimit} { + punk::netbox::man::system::dupkeylist_setfirst nextopts -limit $maxresults + } + set to_go [expr {$maxresults - [llength $resultlist]}] + while {$urlnext ne "null"} { + if {$urlnext ne ""} { + set urlnext_params [punk::netbox::man::uri_get_querystring_as_keyval_list $urlnext] + if {[punk::netbox::man::system::dupkeylist_getfirst $nextopts -limit] > $to_go} { + punk::netbox::man::system::dupkeylist_setfirst urlnext_params limit $to_go } + #sync to -limit,-offset from the url's limit, offset values + punk::netbox::man::system::optionlistvar_sync_from_urlparams nextopts $urlnext_params } - puts "-->next:$next nextopts:$nextopts vals:$vals" + puts "-->next:$urlnext nextopts:$nextopts vals:$vals" set resultd [punk::netbox::ipam::prefixes_list $token {*}$nextopts -RETURN dict {*}$vals] - set next [dict get $resultd next] + set urlnext [dict get $resultd next] set batch [dict get $resultd results] lappend resultlist {*}$batch + + set to_go [expr {$maxresults - [llength $resultlist]}] + if {$to_go <= 0} {break} incr requests_allowed -1 if {$requests_allowed < 1} {break} } @@ -252,8 +262,6 @@ tcl::namespace::eval punk::netbox::man::prefixes { set argd [punk::args::parse $args withid "::punk::netbox::man::prefixes available-ips_list"] set token tclread ;#todo - set next "" - set requests_allowed 1000 ;#review set resultlist [::list] set opts [dict get $argd opts] set valuedict [dict get $argd values] @@ -274,17 +282,26 @@ tcl::namespace::eval punk::netbox::man::prefixes { } #Now opts is a list with possible repeated options! (for flags that have -multiple true) - #No paging available at endpoint ipam/prefixes/available-ips - but we can still use limit (but offset doesn't seem to work + #No paging available at endpoint ipam/prefixes/available-ips - but we can still use limit (but offset doesn't seem to work) + #REVIEW - no way to know if *all* available in a prefix were returned - could/should? have been limited by server setting + #Especially in an ipv6 context - we're *very* unlikely to want to try to get all! (even for a /16 ipv4 it's probably not a very sensible query) + #Default netbox server limit seems to be 1000? review + #setting -limit 0 seems to allow this to be overridden - giving results bounded only by size of the prefix? set resultlist [punk::netbox::ipam::prefixes_available-ips_list $token {*}$nextopts -RETURN list {*}$vals] if {$outer_return in {table tableobject}} { package require textblock set t [textblock::list_as_table -return tableobject -colheaders {address family vrf}] foreach ip $resultlist { + if {[dict exists $ip vrf id]} { + set vrfinfo "[dict get $ip vrf id]: [dict get $ip vrf name]" + } else { + set vrfinfo "-" + } set r [::list\ [dict get $ip address]\ [dict get $ip family]\ - "[dict get $ip vrf id]: [dict get $ip vrf name]"\ + $vrfinfo\ ] $t add_row $r } @@ -334,7 +351,8 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { lappend PUNKARGS [::list\ [punk::args::resolved_def -antiglobs {apicontextid @leaders @values -RETURN} -override {@id {-id "::punk::netbox::man::ip-addresses list"}} ::punk::netbox::ipam::ip-addresses_list]\ - {-RETURN -default table -choices {table tableobject list}}\ + {-RETURN -default table -choices {table tableobject list linelist}}\ + {-MAXRESULTS -type integer -default -1}\ {@values -min 0 -max 0}\ ] @@ -343,14 +361,17 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { set argd [punk::args::parse $args withid "::punk::netbox::man::ip-addresses list"] set token tclread ;#todo - set next "" - set requests_allowed 1000 ;#review + set urlnext "" + set requests_allowed 1000 ;#Sanity check - consider making an option - review set resultlist [::list] set opts [dict get $argd opts] set vals [dict get $argd values] set multis [dict get $argd multis] set outer_return [dict get $opts -RETURN] - set opts [dict remove $opts -RETURN] ;#opts from punk::args::parse is a dict (no dup keys) - can use 'dict remove' safely + set opts [dict remove $opts -RETURN] ;#opts from punk::args::parse is a dict (no dup keys) - can use 'dict remove' safely + set maxresults [dict get $opts -MAXRESULTS] + set opts [dict remove $opts -MAXRESULTS] + set initial_pagelimit [dict get $opts -limit] #we can't just pass through 'multi' opts even if only one was supplied - list level is wrong set nextopts [::list] dict for {opt val} $opts { @@ -364,27 +385,33 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { } #Now opts is a list with possible repeated options! (for flags that have -multiple true) - while {$next ne "null"} { - if {$next ni [::list "" null]} { - set plist [punk::netbox::man::uri_get_querystring_as_keyval_list $next] - #don't use any dict write operations on plist/nextopts - can destroy dup keys - set p_offset [lsearch -stride 2 $plist offset] ;#only search in 'key' positions - for -offset we are only expecting/allowing a single entry - if {$p_offset != -1} { - lappend nextopts -offset [lindex $plist $p_offset+1] - } - set p_limit [lsearch -stride 2 $plist limit] - if {$p_limit != -1} { - lappend nextopts -limit [lindex $plist $p_limit+1] + if {$maxresults == -1} { + set maxresults $initial_pagelimit + } + if {$maxresults < $initial_pagelimit} { + punk::netbox::man::system::dupkeylist_setfirst nextopts -limit $maxresults + } + set to_go [expr {$maxresults - [llength $resultlist]}] + while {$urlnext ne "null"} { + if {$urlnext ne ""} { + set urlnext_params [punk::netbox::man::uri_get_querystring_as_keyval_list $urlnext] + if {[punk::netbox::man::system::dupkeylist_getfirst $nextopts -limit] > $to_go} { + punk::netbox::man::system::dupkeylist_setfirst urlnext_params limit $to_go } + punk::netbox::man::system::optionlistvar_sync_from_urlparams nextopts $urlnext_params } - puts "-->next:$next nextopts:$nextopts vals:$vals" + puts "-->next:$urlnext nextopts:$nextopts vals:$vals" set resultd [punk::netbox::ipam::ip-addresses_list $token {*}$nextopts -RETURN dict {*}$vals] - set next [dict get $resultd next] + set urlnext [dict get $resultd next] set batch [dict get $resultd results] lappend resultlist {*}$batch + + set to_go [expr {$maxresults - [llength $resultlist]}] + if {$to_go <= 0} {break} incr requests_allowed -1 if {$requests_allowed < 1} {break} } + if {$outer_return in {table tableobject}} { package require textblock set t [textblock::list_as_table -return tableobject -colheaders {id address family vrf_id tenant status assigned_object_type deviceinfo dns_name description}] @@ -407,11 +434,16 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { set deviceinfo - } } + if {[dict exists $ip vrf id]} { + set vrfinfo "[dict get $ip vrf id]: [dict get $ip vrf name]" + } else { + set vrfinfo "-" + } set r [::list\ [dict get $ip id]\ [dict get $ip address]\ [dict get $ip family label]\ - [dict get $ip vrf id]\ + $vrfinfo\ $tenant\ [dict get $ip status value]\ [dict get $ip assigned_object_type]\ @@ -431,14 +463,75 @@ tcl::namespace::eval punk::netbox::man::ip-addresses { tableobject { return $t } + linelist { + set ret "" + foreach r $resultlist { + append ret $r \n + } + return $ret + } + default { + return $resultlist + } } - return $resultlist - #return [showdict $resultd] } } +tcl::namespace::eval punk::netbox::man::system { + + #update/add specific members of optionlistvar params in dashed -option format from urlparams in undashed format + #members: offset,limit -> -offset,-limit + #Must support duplicate keys in either *list* + #i.e don't use any dict write operations on paramlistvar - can destroy dup keys + proc optionlistvar_sync_from_urlparams {optionlistvar urlparams} { + upvar 1 $optionlistvar optionlist + + set posn_url_offset [lsearch -stride 2 $urlparams offset] ;#only search in 'key' positions - for offset,limit we are only expecting/allowing a single entry + set posn_option_offset [lsearch -stride 2 $optionlist -offset] + if {$posn_url_offset != -1} { + if {$posn_option_offset != -1} { + lset optionlist $posn_option_offset+1 [lindex $urlparams $posn_url_offset+1] + } else { + lappend optionlist -offset [lindex $urlparams $posn_url_offset+1] + } + } else { + set optionlist [lremove $optionlist $posn_option_offset $posn_option_offset+1] + } + + set posn_url_limit [lsearch -stride 2 $urlparams limit] + set posn_option_limit [lsearch -stride 2 $optionlist -limit] + if {$posn_url_limit != -1} { + if {$posn_option_limit != -1} { + lset optionlist $posn_option_limit+1 [lindex $urlparams $posn_url_limit+1] + } else { + lappend optionlist -limit [lindex $urlparams $posn_url_limit+1] + } + } else { + set optionlist [lremove $optionlist $posn_option_limit $posn_option_limit+1] + } + return + } + + #single level dict-like list with possible duplicate keys + #These functions should be used for keys which we *dont'* expect to be duplicates + #functions are names getfirst,setfirst to make the behaviour explicit/apparent + proc dupkeylist_getfirst {dupkeylist topkey} { + set posn [lsearch -stride 2 $dupkeylist $topkey] + if {$posn == -1} {return} + return [lindex $dupkeylist $posn+1] + } + proc dupkeylist_setfirst {dupkeylistvar topkey val} { + upvar 1 $dupkeylistvar dupkeylist + set posn [lsearch -stride 2 $dupkeylist $topkey] + if {$posn == -1} { + lappend dupkeylist $topkey $val + return $dupkeylist + } + lset dupkeylist $posn+1 $val + } +} # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # Secondary API namespace