You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1991 lines
76 KiB

# -*- tcl -*-
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm
#
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem.
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# (C) 2025
#
# @@ Meta Begin
# Application punk::netbox 999999.0a1.0
# Meta platform tcl
# Meta license MIT
# @@ Meta End
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin shellspy_module_punk::netbox 0 999999.0a1.0]
#[copyright "2025"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[require punk::netbox]
#[keywords module]
#[description]
#[para] -
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Overview]
#[para] overview of punk::netbox
#[subsection Concepts]
#[para] -
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection dependencies]
#[para] packages used by punk::netbox
#[list_begin itemized]
package require Tcl 8.6-
package require http
package require rest
package require punk::args
#*** !doctools
#[item] [package {Tcl 8.6}]
#[item] [package {http}]
# #package require frobz
# #*** !doctools
# #[item] [package {frobz}]
#*** !doctools
#[list_end]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::netbox::class {
#*** !doctools
#[subsection {Namespace punk::netbox::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::netbox {}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Internal]
tcl::namespace::eval punk::netbox::system {
#*** !doctools
#[subsection {Namespace punk::netbox::system}]
#[para] Internal functions that are not part of the API
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
punk::args::define {
@id -id ::punk::netbox::system::make_rest_func
@leaders -min 2 -max 2
commandname -help\
"Fully qualified commandname.
There must be an existing punk::args definition with @id
directive -id matching the name"
endpoint -help\
"The subpath to be appended to the base url.
e.g api/ipam/ip-addresses/
api/ipam/ip-addresses/{id}/"
-verb -default get -choices {get post patch head put delete}
-body -default optional -choicecolumns 2 -choices {none optional required mime_multipart}\
-choicelabels {
none\
" The call has no request body,
none must be supplied."
optional\
" A request body can be supplied,
but is not required"
required\
" A request body must be supplied."
mime_multipart\
" A request body must be supplied
and will be interpreted as each
argument representing one part of
a mime/multipart document. Arguments
must be lists containing 2 elements,
a list of header keys and values,
and the mime part body, in this order."
}
}
#A somewhat sanitized config for outputting to stderr etc
#Obscure at least full Authorization Token
#todo - other headers?
proc obscured_config {cfg} {
set sanconfig $cfg
if {[dict exists $cfg headers]} {
set hdrs [dict get $cfg headers]
if {[dict exists $hdrs Authorization]} {
set auth [dict get $hdrs Authorization]
if {[dict exists $auth Token]} {
dict set auth Token "[string range [dict get $auth Token] 0 5]..."
dict set hdrs Authorization $auth
dict set sanconfig headers $hdrs
}
}
}
return $sanconfig
}
proc make_rest_func {args} {
set argd [punk::args::parse $args withid ::punk::netbox::system::make_rest_func]
lassign [dict values $argd] leaders opts values received
set commandname [dict get $leaders commandname]
set endpoint [dict get $leaders endpoint]
set verb [dict get $opts -verb]
set body [dict get $opts -body]
set custom [dict create\
%commandname% $commandname\
%endpoint% $endpoint\
%verb% $verb\
%body% $body\
%showpagedict% {!@@results @@results/@*/@*.@*}\
%showpagedict2% {@@results/@*/@*.@* !@@results}\
%showdict% {*}\
%showdict2% {*/*}\
%showlistofdicts% {@*/@*.@*}\
]
if {$commandname eq "::punk::netbox::status"} {
#we get duplicate django-version for %showdict% - todo - something.
dict set custom %showdict% {@@django-version @@installed-apps/@*.@* !@@installed-apps}
dict set custom %showdict2% {@@installed-apps/@*.@* !@@installed-apps}
}
set procbody [string map $custom {
set argd [punk::args::parse $args withid %commandname%]
lassign [dict values $argd] leaders opts values received solos multis
set apicontextid [dict get $leaders apicontextid]
if {[dict exists $received -RETURN]} {
set returntype [dict get $opts -RETURN]
} else {
if {[dict exists $opts -RETURN]} {
#not received - but has default
set returntype [dict get $opts -RETURN]
} else {
#fallback if -RETURN was defined without a default or was omitted
set returntype dict
}
}
set FORCE 1
if {[dict exists $opts -FORCE]} {
set FORCE [dict get $opts -FORCE]
}
set query [list] ;#use list not dict - allows repeated params
dict for {k val} $opts {
switch -- $k {
-CUSTOM_PARAM {
#'-multiple true'
foreach kv $val {
lassign $kv paramname value
lappend query $paramname $value
}
}
-RETURN {
#ignore - already handled
}
default {
if {[string match *_FILTER $k]} {
#all _FILTER methods are '-multiple true' - so are present in $opts as a single key with a value that is a list
#e.g -X_Y_FILTER "blah"
set parts [split $k _]
set name1 [string range [string tolower [lindex $parts 0]] 1 end] ;#strip leading dash off first part
set nametail [string tolower [lrange $parts 1 end-1]]
set paramname [join [list $name1 {*}$nametail] _]
foreach fv $val {
lassign $fv filter value ;#filter is n,gte,lte etc
lappend query ${paramname}__$filter $value
}
} else {
set paramname [string range $k 1 end]
if {$paramname in $multis} {
foreach v $val {
lappend query $paramname $v
}
} else {
lappend query $paramname $val
}
}
}
}
}
set body %body%
switch -- $body {
required {
set requestbody [dict get $values body]
}
optional {
if {[dict exists $received body]} {
set requestbody [dict get $values body]
} else {
set requestbody ""
}
}
}
upvar ::punk::netbox::contexts contexts
if {![dict exists $contexts $apicontextid]} {
error "specified contextid '$apicontextid' not found"
}
set config [dict create\
format json\
result json\
]
#rest api documentation is unclear on 'result' field
#note our default: result json
#this actually converts the json to a dict
dict set config headers [list Authorization [list Token [dict get $contexts $apicontextid token value]]]
if {$returntype in "json jsondump"} {
#if we set result json - we get a dict instead of json :/
dict set config result raw
}
if {$body in {required optional}} {
#content type for the request data
dict set config headers content-type "application/json"
}
#variable headerdict
#set config [dict create\
# headers $headerdict\
#]
set url [dict get $contexts $apicontextid url value]
set endpoint "%endpoint%"
if {[string first {{id}} $endpoint] != -1} {
set id [dict get $values id]
set endpoint [string map [list {{id}} $id] $endpoint]
}
#todo - only show if debug (and obscure Authorization Token)
set sanconfig [punk::netbox::system::obscured_config $config]
puts stderr "url:${url}$endpoint query:'$query' verb:%verb% config:'$sanconfig'"
if {$FORCE} {
#FORCE is true for most operations (and no -FORCE option even available) but the option exists and defaults to false for specifically unsafe
#e.g delete operations on entire endpoints
if {$body in {required optional}} {
set result [::rest::%verb% ${url}$endpoint $query $config $requestbody]
} else {
set result [::rest::%verb% ${url}$endpoint $query $config]
}
} else {
puts stderr "%commandname% not called because -FORCE is false"
set sanconfig [punk::netbox::system::obscured_config $config]
puts "url:${url}$endpoint query:'$query' verb:%verb% config:'$sanconfig'"
return
}
switch -exact -- $returntype {
showpagedict {
#return [punk::lib::showdict $result !@@results @@results/@*/@*.@*]
return [punk::lib::showdict $result %showpagedict%]
}
showpagedict2 {
#return [punk::lib::showdict $result @@results/@*/@*.@* !@@results]
return [punk::lib::showdict $result %showpagedict2%]
}
showdict {
return [punk::lib::showdict $result %showdict%]
}
showdict2 {
return [punk::lib::showdict $result %showdict2%]
}
showlist {
return [punk::lib::showdict -roottype list $result]
}
showlistofdicts {
return [punk::lib::showdict $result %showlistofdicts%]
}
jsondump {
package require huddle::json
#pretty-print via huddle (inefficient review)
set h [huddle::json::json2huddle parse $result]
return [huddle::jsondump $h]
}
linelist {
set ret ""
foreach r $result {
append ret $r \n
}
return $ret
}
default {
#plain result: (list or dict) or json - the counterintuitive 'result' field set to raw above sets the rest resulting format to json
return $result
}
}
}]
proc $commandname {args} $procbody
}
}
tcl::namespace::eval punk::netbox {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection {Namespace punk::netbox}]
#[para] Core API functions for punk::netbox
#[list_begin definitions]
variable PUNKARGS
variable has_tls
set has_tls [expr {![catch {package require tls}]}]
if {$has_tls} {
::http::register https 443 ::tls::socket
}
variable ipam
#TEMP - todo
variable headerdict
set headerdict [dict create\
Authorization "Token af65b993000874eaefeca0fa02b0d86014e48365"\
]
#temp
variable url https://www.netbox1.intx.com.au/
variable contexts [dict create]
variable context_id 0
proc api_context_names {} {
variable contexts
return [dict keys $contexts]
}
lappend PUNKARGS [list {
@id -id ::punk::netbox::api_contexts
@cmd -name punk::netbox::api_contexts -help\
"Show in-memory api contexts.
These are named contexts for calling
the NETBOX rest api.
They are loaded using api_contexts_load from
a .toml configuration file, or created using
api_context_create."
-return -default table -choices {table tableobject dict}
-fields -type list -default {url tokentail comment} -choices {url token tokentail comment *} -choicemultiple {0 -1} -choicerestricted 0 -help\
"The * token can be included in the list of specified
fields, and represents any other available fields found
from the matched contexts"
@values -min 0 -max 1
globname -default * -help\
"pattern to match the context name(s)"
}]
proc api_contexts {args} {
set argd [punk::args::parse $args withid ::punk::netbox::api_contexts]
lassign [dict values $argd] leaders opts values received
set returntype [dict get $opts -return]
set fields [dict get $opts -fields]
set globname [dict get $values globname]
variable contexts
set matches [dict keys $contexts $globname]
if {"*" in $fields} {
set starposn [lsearch -exact $fields *]
set before [lrange $fields 0 $starposn-1]
set after [lrange $fields $starposn+1 end]
set allspecified [list {*}$before {*}$after]
# use * as placeholder for all others not specified - retain order of specified columns
set fields [list]
#check fields in all matches
set starfields [list]
if {"tokentail" ni $allspecified} {
#calculated column
lappend starfields tokentail
}
foreach k $matches {
set contextinfo [dict get $contexts $k]
dict for {valkey valinfo} $contextinfo {
if {$valkey ni $allspecified && $valkey ni $starfields} {
lappend starfields $valkey
}
}
}
set fields [list {*}$before {*}$starfields {*}$after]
}
switch -- $returntype {
table - tableobject {
package require textblock
set t [textblock::table -return tableobject -minwidth 75 -headers [list contextid {*}$fields]]
foreach k $matches {
set contextinfo [dict get $contexts $k]
set tokentail ""
if {"tokentail" in $fields} {
#computed column
if {[dict exists $contextinfo token]} {
set tokentail [string range [dict get $contextinfo token value] end-5 end]
}
}
set rowdata [list $k]
foreach f $fields {
if {[dict exists $contextinfo $f value]} {
lappend rowdata [dict get $contextinfo $f value]
} else {
if {$f eq "tokentail"} {
lappend rowdata $tokentail
} else {
lappend rowdata ""
}
}
}
$t add_row $rowdata
}
if {$returntype eq "table"} {
set tableview [$t print]
$t destroy
return $tableview
} else {
return $t
}
}
dict {
set result [dict create]
foreach k $matches {
set contextinfo [dict get $contexts $k]
set tokentail ""
if {"tokentail" in $fields} {
#computed column
if {[dict exists $contextinfo token]} {
set tokentail [string range [dict get $contextinfo token value] end-5 end]
}
}
dict set result $k {} ;#ensure record is output even if empty fieldlist
foreach f $fields {
if {[dict exists $contextinfo $f value]} {
dict set result $k $f [dict get $contextinfo $f value]
} else {
if {$f eq "tokentail"} {
dict set result $k tokentail $tokentail
}
}
}
#dict for {valkey valinfo} $contextinfo {
# dict set result $k $valkey [dict get $valinfo value]
#}
}
return $result
}
}
}
#get api handle(s) for a netbox server (with url and token) to pass to the punk::netbox api functions
lappend PUNKARGS [list {
@id -id ::punk::netbox::api_context_load
@cmd -name punk::netbox::api_context_load -help\
"Load API context information (url token)
from a .toml file in the data directory
or from a specified file.
To create an initial file, use api_context
to create one or more named configurations
specifying the url and authentication token.
Then use api_context_save to persist them."
@opts
-contextname -default * -help\
"Name of an API context or a pattern for
which contexts to load from the file."
@values
filepath -default "" -type file
}]
proc api_context_load {args} {
set argd [punk::args::parse $args withid ::punk::netbox::api_context_load]
lassign [dict values $argd] leaders opts values received
set contextglob [dict get $opts -contextname]
set filepath [dict get $values filepath]
if {$filepath eq ""} {
set filepath [_datafile]
}
if {![file exists $filepath]} {
error "No existing datafile at '$filepath'\nUse api_context_create to configure a context and save it with api_context_save"
}
package require tomlish
set tomldata [readFile $filepath]
set tomlish [tomlish::from_toml $tomldata] ;#intermediate (unvalidated) representation of toml data - maintaining whitespace and comments
set tomldict [tomlish::to_dict $tomlish] ;#lossy conversion to a programmatic structure (loss is of comments, whitespace)
variable contexts
#merge into any existing-in-memory loaded/created contexts
set loaded [list]
dict for {contextid contextinfo} $tomldict {
if {[string match $contextglob $contextid]} {
if {![dict exists $contextinfo url]} {
puts "api_context_load warning: Loaded context $contextid is missing 'url' key"
}
if {![dict exists $contextinfo token]} {
puts "api_context_load warning: Loaded context $contextid is missing 'token' key"
}
dict set contexts $contextid $contextinfo
lappend loaded $contextid
}
}
return $loaded
}
lappend PUNKARGS [list {
@id -id ::punk::netbox::api_context_create
@cmd -name punk::netbox::api_context_create -help\
"Create an in-memory configuration for an API context.
This consists of a name (contextid) under which a
url and authentication token are stored.
It can optionally be persisted using api_context_save
to the file of your choice, or to a reasonable default
location. (see _datafile).
The api_context_load function can be used to retrieve
previously stored contextids instead of calling this
function each time.
A contextid is required when calling the netbox rest api
functions such as ipam::vrfs
This allows easy intermixing of calls to either the same
or different servers using the different permissions
granted by each token.
"
@leaders -min 1 -max 1
contextid -type string -help\
"Name for the api context.
If saved to a .toml file, this
will be the name of a toplevel table
containing configuration elements such
as url and token."
@opts
-property_value -type list -minsize 2 -maxsize 2 -multiple 1 -help\
"custom property and value.
e.g
property_value {comment {test comment}}"
@values -min 2 -max 2
url -type string -help\
"Base url of netbox server"
token -type string -help\
"Netbox API authentication token"
}]
proc api_context_create {args} {
set argd [punk::args::parse $args withid ::punk::netbox::api_context_create]
lassign [dict values $argd] leaders opts values received
set contextid [dict get $leaders contextid]
if {[dict exists $received -property_value]} {
set propvals [dict get $opts -property_value] ;#multiple - as pairs
} else {
set propvals [list]
}
set baseurl [dict get $values url]
set token [dict get $values token]
variable contexts
if {[dict exists $contexts $contextid]} {
error "api_context_create a context with id '$contextid' already exists."
}
set allprops [dict create url [dict create type STRING value $baseurl] token [dict create type STRING value $token]]
foreach pv $propvals {
lassign $pv p v
if {$p in {url token}} {
puts stderr "ignoring -property_value $p - invalid - already specified in arguments"
}
#todo - multiline?
dict set allprops $p [dict create type STRING value $v]
}
dict set contexts $contextid $allprops
return $contextid
}
proc _homedir {} {
if {[info exists ::env(HOME)]} {
set home [file normalize $::env(HOME)]
} else {
#not available on 8.6? ok will error out here.
set home [file tildeexpand ~]
}
return $home
}
lappend PUNKARGS [list {
@id -id ::punk::netbox::_datafile
@cmd -name punk::netbox::_datafile -help\
"Get the path for the default storage file
used when an explicit path is not given by
the caller to the api_context load/save
functions. This file is in toml format.
On any platform the XDG_DATA_HOME env var
can be used to override the location, but
on Windows the LOCALAPPDATA env var will
specifiy the location if XDG_DATA_HOME is
not set.
Interfacing with a proper secret store
should be considered as an alternative.
On non Windows platforms:
The XDG_DATA_HOME env var is the preferred
choice of location - considered slightly more
secure than XDG_CONFIG_HOME.
A folder under the user's home directory,
at .local/share/punk/netbox is chosen if
XDG_DATA_HOME is not configured.
"
@leaders -min 0 -max 0
@opts
-quiet -type none -help\
"Suppress warning given when the folder does
not yet exist"
@values -min 0 -max 0
}]
proc _datafile {args} {
set argd [punk::args::parse $args withid ::punk::netbox::_datafile]
lassign [dict values $argd] leaders opts values received
set be_quiet [dict exists $received -quiet]
set was_noisy 0
if {[info exists ::env(XDG_DATA_HOME)]} {
set data_home $::env(XDG_DATA_HOME)
} else {
if {$::tcl_platform(platform) eq "windows"} {
set data_home $::env(LOCALAPPDATA)
} else {
set data_home [file join [_homedir] .local share]
if {!$be_quiet} {
puts stderr "Environment variable XDG_DATA_HOME does not exist - consider setting it if $data_home is not a suitable location"
set was_noisy 1
}
}
}
if {!$be_quiet && ![file exists $data_home]} {
#parent folder for 'punk' config dir doesn't exist
set msg "configuration location XDG_DATA_HOME or ~/.local/share (or LOCALAPPDATA on windows) at path '$data_home' does not yet exist"
append msg \n " - please create it and/or set the appropriate env var."
puts stderr $msg
set was_noisy 1
}
set punk_netbox_data_dir [file join $data_home punk netbox]
if {!$be_quiet && ![file exists $punk_netbox_data_dir]} {
set msg "punk::netbox data storage folder at $punk_netbox_data_dir does not yet exist."
append msg \n " It will be created if api_context_save is called without specifying an alternate location."
puts stderr $msg
set was_noisy 1
}
if {!$be_quiet && $was_noisy} {
puts stderr "punk::netbox::_datafile - call with -quiet option to suppress these messages"
}
return [file join $punk_netbox_data_dir netbox_api_contexts.toml]
}
lappend PUNKARGS [list {
@id -id ::punk::netbox::api_context_save
@cmd -name punk::netbox::api_context_save -help\
""
@values
contextid -type string -help\
"Name for the api context.
If saved to a .toml file, this
will be the name of a toplevel table
containing configuration elements such
as url and token."
filepath -default "" -optional 1 -type file -help\
"Path of .toml configuration file containing
API url and token information.
If empty it will store under XDG_DATA_DIR
if the env var is defined, or in the
corresponding location within ~/.local/share.
In both cases the subfolder netbox/punk will
be used.
These locations are fairly reasonable for
sensitive data - but as tokens are not
encrypted, a proper security store should be
used instead if your risk-policy requires
more serious security.
"
}]
proc api_context_save {args} {
set argd [punk::args::parse $args withid ::punk::netbox::api_context_save]
lassign [dict values $argd] leaders opts values received
set contextid [dict get $values contextid]
set filepath [dict get $values filepath]
variable contexts
if {![dict exists $contexts $contextid]} {
error "punk::netbox::api_context_save error. No context with id '$contextid' exists. Load from file, or create it using punk::netbox::api_context"
}
if {$filepath eq ""} {
set filepath [_datafile -quiet]
set filefolder [file dirname $filepath]
if {![file exists $filefolder]} {
file mkdir $filefolder
}
}
set configdir [file dirname $filepath]
if {![file exists $configdir]} {
error "api_context_save error: folder $configdir doesn't exist"
}
package require tomlish
if {[file exists $filepath]} {
set existing_toml [readFile $filepath]
set tomlish [tomlish::from_toml $existing_toml]
set data_dict [tomlish::to_dict $tomlish]
if [dict exists $data_dict $contextid] {
#todo - nondestructive merge - don't destroy comments/formatting of existing records
#if we use to_dict on the existing tomlish - we lose comments etc
#also from_dict doesn't yet produce canonical nice-for-humans tomlish/toml
#merge
puts stderr "contextid '$contextid' exists in file $filepath"
puts stderr "Merge not implemented.."
set newfiledata ""
} else {
#append to existing toml data
set newdict [dict create $contextid [dict get $contexts $contextid]]
#we store our contexts in a structure already suitable for toml
# (ie one where we tag strings,ints e.g {type STRING value "etc"})
set newtomlish [tomlish::from_dict $newdict]
set newtoml [tomlish::to_toml $newtomlish]
set newfiledata $existing_toml\n$newtoml
}
} else {
set newdict [dict create $contextid [dict get $contexts $contextid]]
set newtomlish [tomlish::from_dict $newdict]
set newtoml [tomlish::to_toml $newtomlish]
set newfiledata $newtoml
}
if {$newfiledata ne ""} {
writeFile $filepath $newfiledata
puts stderr "saved [string length $newfiledata] bytes to '$filepath'"
}
}
namespace eval argdoc {
set _page_options {
-limit -default 100 -type integer -help\
"Each REST query returns a maximum number
of results. This can be set to 0 to mean
no limit - but it is still restricted to
the max configured on the server. (1000?)
This is effectively the page-size of the
results. To retrieve more than a page, the
next and previous urls can be iterated over."
-offset -default 0 -type integer
}
set _create_update_options {
-created
-created__gte
-created__lte
-last_updated
-last_updated__gte
-last_updated__lte
}
set _tenant_options {
-tenant_group_id
-tenant_group_id__n
-tenant_group
-tenant_group__n
-tenant_id
-tenant_id__n
-tenant
-tenant__n
}
set _region_options {
-region_id
-region
}
set _site_options {
-site_group_id
-site_group_id__n
-site_group
-site_group__n
-site_id
-site_id__n
-site
-site__n
}
set _group_options {
-group_id
-group_id__n
-group
-group__n
}
set _contact_options {
-contact
-contact__n
-contact_role
-contact_role__n
-contact_group
-contact_group__n
}
set _role_options {
-role_id
-role_id__n
-role
-role__n
}
set _filter_string [list\
"ie <str>\n Exact match\n(case-insensitive)"\
"nie <str>\n Inverse exact match\n(case-insensitive)"\
"n <str>\n Not equal to"\
"ic <str>\n Contains\n (case-insensitive)"\
"nic <str>\n Does not contain\n (case-insensitive)"\
"isw <str>\n Starts with\n (case-insensitive)"\
"nisw <str>\n Does not start with\n (case-insensitive)"\
"iew <str>\n Ends with\n (case-insensitive)"\
"niew <str>\n Does not end with\n (case-insensitive)"\
"empty <bool>\n Is empty/null"\
]
set _filter_number [list\
"n <num>\n Not equal to"\
"lte <num>\n Less than or equal"\
"lt <num>\n Less than"\
"gte <num>\n Greater than or equal"\
"gt <num>\n Greater than"\
]
set _CUSTOM_PARAMS {
-CUSTOM_PARAM -type list -minsize 2 -maxsize 2 -multiple 1 -help\
"Specify a parameter not in this API
e.g -CUSTOM_PARAM {mytag blah}"
}
set _RETURN_PAGEDICT {
-RETURN -type string -choices {dict showpagedict showpagedict2 json jsondump} -choicelabels {
dict\
" Tcl dictionary
(fastest)"
showpagedict\
" human readable dict display
with same order as dict."
showpagedict2\
" human readable dict display
results first, page metadata last."
} -help\
"Options for returned data.
Note that showdict results are relatively slow, especially for large resultsets"
}
set _RETURN_DICT {
-RETURN -type string -choices {dict showdict showdict2 json jsondump} -choicelabels {
dict\
" Tcl dictionary
(fastest)"
showdict\
" human readable dict display
with same order as dict."
showdict2\
" human readable dict display
results first metadata last."
} -help\
"Options for returned data.
Note that showdict results are relatively slow, especially for large resultsets"
}
set _RETURN_LIST {
-RETURN -type string -choices {list linelist showlist json jsondump} -choicelabels {
list\
" Tcl list
(fastest)"
linelist\
" raw list with newline after each item"
showlist\
" human readable list display"
} -help\
"Options for returned data.
Note that showlist results are relatively slow, especially for large resultsets"
}
set _RETURN_LISTOFDICTS {
-RETURN -type string -choices {list linelist showlist json jsondump} -choicelabels {
list\
" Tcl list
(fastest)"
linelist\
" raw list with newline after each item"
showlistofdicts\
" human readable display list of dicts"
} -help\
"Options for returned data.
Note that showlist results are relatively slow, especially for large resultsets"
}
set _RETURN_STATUS {
-RETURN -type string -default showdict2 -choices {dict showdict showdict2 json jsondump} -choicelabels {
dict\
" Tcl dictionary"
showdict\
" human readable dict display"
showdict2\
" human readable dict display
installed-apps first."
} -help\
"Options for returned data."
}
set _name_filter_help "Paired search filter for name:\n"
append _name_filter_help [textblock::list_as_table -columns 4 -show_hseps 1 $_filter_string]
set _description_filter_help "Paired search filter for description:\n"
append _description_filter_help [textblock::list_as_table -columns 4 -show_hseps 1 $_filter_string]
set string_filter_help "Paired search filter for string:\n"
append _string_filter_help [textblock::list_as_table -columns 4 -show_hseps 1 $_filter_string]
#n, lte, lt, gte, gt
#e.g virtualization/virtual-machine vcpus, memory, disk
set number_filter_help "Paired search filter for number:\n"
append _number_filter_help [textblock::list_as_table -columns 3 -show_hseps 1 $_filter_number]
}
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::status
@cmd -name punk::netbox::status -help\
"status_list
GET request for endpoint /status/
Netbox's current operational status
"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_STATUS]\
{
@values -min 0 -max 0
}]
::punk::netbox::system::make_rest_func ::punk::netbox::status api/status/ -verb get -body none
#test function - todo use punk::netbox::system::make_rest_func
#proc vrfs {args} {
# set argd [punk::args::parse $args withid ::punk::netbox::vrfs]
# lassign [dict values $argd] leaders opts values received
# set apicontextid [dict get $leaders apicontextid]
# set query [dict create]
# dict for {k v} $opts {
# if {$k eq "-CUSTOM_PARAM"} {
# foreach custval $v {
# lassign $custval param value
# dict set query $param $value
# }
# } elseif {[string match *_FILTER $k]} {
# set field [string range [string tolower [lindex [split $k _] 0]] 1 end] ;# -NAME_FILTER -> name
# foreach fv $v {
# lassign $fv filter value
# dict set query ${field}__$filter $value
# }
# } else {
# dict set query [string range $k 1 end] $v
# }
# }
# variable contexts
# if {![dict exists $contexts $apicontextid]} {
# error "specified contextid '$apicontextid' not found"
# }
# set config [dict create\
# result json\
# ]
# dict set config headers [list Authorization [list Token [dict get $contexts $apicontextid token value]]]
# #variable headerdict
# #set config [dict create\
# # headers $headerdict\
# # result json\
# #]
# #variable url
# set url [dict get $contexts $apicontextid url value]
# puts "${url}api/ipam/vrfs/ '$query' '$config'"
# rest::get ${url}api/ipam/vrfs/ $query $config
#}
#set ipam(vrfs) [dict create\
# url https://www.netbox1.intx.com.au/api/ipam/vrfs/\
# method get\
# result json\
# body none\
# headers $headerdict\
# opt_args {id: name: limit:100 offset:0}
#]
#set ipam(ip-addresses) [dict create\
# url https://www.netbox1.intx.com.au/api/ipam/ip-addresses/\
# method get\
# headers $headerdict\
# opt_args {parent: limit:100 offset:0}
#]
#set ipam(prefixes) [dict create\
# url https://www.netbox1.intx.com.au/api/ipam/prefixes/\
# method get\
# headers $headerdict\
# opt_args {prefix: limit:100 offset:0}
#]
#rest::create_interface ::punk::netbox::ipam
#proc sample1 {p1 n args} {
# #*** !doctools
# #[call [fun sample1] [arg p1] [arg n] [opt {option value...}]]
# #[para]Description of sample1
# #[para] Arguments:
# # [list_begin arguments]
# # [arg_def tring p1] A description of string argument p1.
# # [arg_def integer n] A description of integer argument n.
# # [list_end]
# return "ok"
#}
#*** !doctools
#[list_end] [comment {--- end definitions namespace punk::netbox ---}]
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::netbox::dcim {
namespace export {[a-z]*}
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::dcim::devices_list
@cmd -name punk::netbox::dcim::devices_list -help\
"tenancy_tenants_list
GET request for endpoint /dcim/devices/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
-id -type integer
-ID_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-name
-NAME_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_name_filter_help}}
-asset_tag -type string
-ASSET_TAG_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_string_filter_help}}
-face -type string
-face__n -type string
-position -type integer
-POSITION_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-airflow -type string
-airflow__n -type string
-vc_position -type integer
-VC_POSITION_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-vc_priority -type integer
-VC_PRIORITY_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
}\
[set ::punk::netbox::argdoc::_create_update_options]\
{
-q -type string
-tag -type string
-tag__n -type string
}\
[set ::punk::netbox::argdoc::_tenant_options]\
[set ::punk::netbox::argdoc::_contact_options]\
{
-local_context_data
-manufacturer_id
-manufacturer_id__n
-manufacturer
-manufacturer__n
-device_type_id
-device_type_id__n
-role_id
-role_id__n
-role
-role__n
-parent_device_id
-parent_device_id__n
-platform_id
-platform_id__n
-platform
-platform__n
}\
[set ::punk::netbox::argdoc::_group_options]\
[set ::punk::netbox::argdoc::_region_options]\
[set ::punk::netbox::argdoc::_site_options]\
{
-location_id -type integer
-location_id__n -type integer
-rack_id -type integer
-rack_id__n -type integer
-cluster_id -type integer
-cluster_id__n -type integer
-model -type string
-model__n -type string
-status -type string
-status__n -type string
-mac_address -type string
-MAC_ADDRESS_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_string_filter_help}}
-serial -type string
-SERIAL_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_string_filter_help}}
-virtual_chassis_id -type integer
-virtual_chassis_id__n -type integer
}\
[set ::punk::netbox::argdoc::_page_options]\
[set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\
[set ::punk::netbox::argdoc::_RETURN_PAGEDICT]\
{
@values -min 0 -max 0
}]
::punk::netbox::system::make_rest_func ::punk::netbox::dcim::devices_list api/dcim/devices/ -verb get -body none
}
tcl::namespace::eval punk::netbox::ipam {
namespace export {[a-z]*}
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::ipam::vrfs_list
@cmd -name punk::netbox::ipam::vrfs_list -help\
"ipam_vrfs_list
GET request for endpoint /ipam/vrfs/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
-id -type integer
-ID_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-name
-NAME_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_name_filter_help}}
-rd -type string -help\
"Route distinguisher in any format"
-enforce_unique
-description -type string -help "Exact Match (case sensitive)"
-DESCRIPTION_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_description_filter_help}}
}\
[set ::punk::netbox::argdoc::_create_update_options]\
{
-q
-tag
}\
[set ::punk::netbox::argdoc::_tenant_options]\
[set ::punk::netbox::argdoc::_region_options]\
[set ::punk::netbox::argdoc::_site_options]\
[set ::punk::netbox::argdoc::_group_options]\
[set ::punk::netbox::argdoc::_role_options]\
{
-status
-available_on_device
-available_on_virtualmachine
}\
[set ::punk::netbox::argdoc::_page_options]\
[set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\
[set ::punk::netbox::argdoc::_RETURN_PAGEDICT]\
{
@values -min 0 -max 0
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::vrfs_list api/ipam/vrfs/ -verb get -body none
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::ipam::vrfs_read
@cmd -name punk::netbox::ipam::vrfs_read -help\
"ipam_vrfs_list
GET request for endpoint /ipam/vrfs/{id}"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 1 -max 1
id -type integer -help\
"A unique integer value identifying this VRF"
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::vrfs_read api/ipam/vrfs/{id}/ -verb get -body none
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::prefixes_list
@cmd -name punk::netbox::ipam::prefixes_list -help\
"ipam_prefixes_list
GET request for endpoint /ipam/prefixes/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
-id -type integer
-ID_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-is_pool
-mark_utilized
-description -type string -help "Exact Match (case sensitive)"
-DESCRIPTION_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_description_filter_help}}
}\
[set ::punk::netbox::argdoc::_create_update_options]\
{
-q -type string -help\
"Query prefixes by substring"
-tag
}\
[set ::punk::netbox::argdoc::_tenant_options]\
[set ::punk::netbox::argdoc::_region_options]\
[set ::punk::netbox::argdoc::_site_options]\
[set ::punk::netbox::argdoc::_group_options]\
[set ::punk::netbox::argdoc::_role_options]\
{
-family
-prefix
-within
-within_include
-contains
-depth
-DEPTH_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-children
-CHILDREN_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-mask_length
-mask_length__gte
-mask_length__lte
-vlan_id -type integer
-vlan_id__n -type integer
-vlan_vid -type integer
-VLAN_VID_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-vrf_id
-vrf
-status
-available_on_device
-available_on_virtualmachine
}\
[set ::punk::netbox::argdoc::_page_options]\
[set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\
[set ::punk::netbox::argdoc::_RETURN_PAGEDICT]\
{
@values -min 0 -max 0
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::prefixes_list api/ipam/prefixes/ -verb get -body none
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::prefixes_create
@cmd -name punk::netbox::ipam::prefixes_create -help\
"ipam_prefixes_create
POST request for endpoint /ipam/prefixes/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 1 -max 1
body -type string -help\
"JSON string"
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::prefixes_create api/ipam/prefixes/{id}/ -verb post -body required
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::prefixes_read
@cmd -name punk::netbox::ipam::prefixes_read -help\
"ipam_prefixes_read
GET request for endpoint /ipam/prefixes/{id}/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 1 -max 1
id -type integer -help\
"A unique integer value identifying this prefix"
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::prefixes_read api/ipam/prefixes/{id}/ -verb get -body none
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::prefixes_available-ips_list
@cmd -name punk::netbox::ipam::prefixes_available-ips_list -help\
"ipam_prefixes_available-ips_list
GET request for endpoint /ipam/prefixes/{id}/available-ips/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_page_options]\
[set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\
[set ::punk::netbox::argdoc::_RETURN_LISTOFDICTS]\
{
@values -min 1 -max 1
id -type integer -help\
"A unique integer value identifying this prefix"
}\
]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::prefixes_available-ips_list api/ipam/prefixes/{id}/available-ips/ -verb get -body none
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::prefixes_available-ips_create
@cmd -name punk::netbox::ipam::prefixes_available-ips_create -help\
"ipam_prefixes_available-ips_create
POST request for endpoint /ipam/prefixes/{id}/available-ips/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 1 -max 2
id -type integer -help\
"A unique integer value identifying this prefix"
body -type string -default "" -help\
{
If empty create a single IP with default values.
(next available IP in prefix)
Create 2 IPs:
[
{"description": "ip1"},
{"description": "ip2"}
]
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. :/
}
}\
]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::prefixes_available-ips_create api/ipam/prefixes/{id}/available-ips/ -verb post -body required
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::ip-addresses_list
@cmd -name punk::netbox::ipam::ip-addresses_list -help\
"ipam_ip-addresses_list
GET request for endpoint /ipam/ip-addresses/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
-id -type integer
-ID_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-dns_name
-DNS_NAME_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_string_filter_help}}
-description -type string -help "Exact Match (case sensitive)"
-DESCRIPTION_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_description_filter_help}}
}\
[set ::punk::netbox::argdoc::_create_update_options]\
{
-q
-tag
}\
[set ::punk::netbox::argdoc::_tenant_options]\
[set ::punk::netbox::argdoc::_region_options]\
[set ::punk::netbox::argdoc::_site_options]\
[set ::punk::netbox::argdoc::_group_options]\
[set ::punk::netbox::argdoc::_role_options]\
{
-family
-parent
-address
-mask_length
-vrf_id
-vrf
-present_in_vrf_id
-present_in_vrf
-device
-device_id
-virtual_machine
-virtual_machine_id
-interface
-interface_id
-vminterface
-vminterface_id
-fhrpgroup_id
-assigned_to_interface
-status
-role
-available_on_device
-available_on_virtualmachine
}\
[set ::punk::netbox::argdoc::_page_options]\
[set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\
[set ::punk::netbox::argdoc::_RETURN_PAGEDICT]\
{
@values -min 0 -max 0
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::ip-addresses_list api/ipam/ip-addresses/ -verb get -body none
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::ip-addresses_read
@cmd -name punk::netbox::ipam::ip-addresses_read -help\
"ipam_ip-addresses_read
GET request for endpoint /ipam/ip-addresses/{id}/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 1 -max 1
id -type integer
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::ip-addresses_read api/ipam/ip-addresses/{id}/ -verb get -body none
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::ip-addresses_create
@cmd -name punk::netbox::ipam::ip-addresses_create -help\
"ipam_ip-addresses_create
POST request for endpoint /ipam/ip-addresses/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 1 -max 1
body -type string -help\
{JSON string
Example:
{
"address": "string",
"vrf": 0,
"tenant": 0,
"status": "active",
"role": "loopback",
"assigned_object_type": "string",
"assigned_object_id": 0,
"nat_inside": 0,
"dns_name": "string",
"description": "string",
"tags": [
{
"name": "string",
"slug": "string",
"color": "string"
}
],
"custom_fields": {}
}
Required: address (IPv4 or IPV6 address with mask)
}
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::ip-addresses_create api/ipam/ip-addresses/ -verb post -body required
punk::args::define {*}[list\
{
@dynamic
@id -id ::punk::netbox::ipam::ip-addresses_bulk_partial_update
@cmd -name punk::netbox::ipam::ip-addresses_bulk_partial_update -help\
"ipam_ip-addresses_bulk_partical_update
PATCH request for endpoint /ipam/ip-addresses/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 1 -max 1
body -type string -help\
{JSON string
model:
{
"address": "string",
"vrf": 0,
"tenant": 0,
"status": "active",
"role": "loopback",
"assigned_object_type": "string",
"assigned_object_id": 0,
"nat_inside": 0,
"dns_name": "string",
"description": "string",
"tags": [
{
"name": "string",
"slug": "string",
"color": "string"
}
],
"custom_fields": {}
}
required: address
}
}]
::punk::netbox::system::make_rest_func ::punk::netbox::ipam::ip-addresses_bulk_partial_update api/ipam/ip-addresses/ -verb patch -body required
}
tcl::namespace::eval punk::netbox::tenancy {
namespace export {[a-z]*}
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::tenancy::tenants_list
@cmd -name punk::netbox::tenancy::tenants_list -help\
"tenancy_tenants_list
GET request for endpoint /tenancy/tenants/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
-id -type integer
-ID_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-name
-NAME_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_name_filter_help}}
-slug -type string
-SLUG_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_string_filter_help}}
-description -type string
-DESCRIPTION_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_string_filter_help}}
}\
[set ::punk::netbox::argdoc::_create_update_options]\
{
-q -type string
-tag -type string
-tag__n -type string
}\
[set ::punk::netbox::argdoc::_tenant_options]\
[set ::punk::netbox::argdoc::_contact_options]\
{
}\
{
}\
[set ::punk::netbox::argdoc::_group_options]\
{
}\
[set ::punk::netbox::argdoc::_page_options]\
[set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\
[set ::punk::netbox::argdoc::_RETURN_PAGEDICT]\
{
@values -min 0 -max 0
}]
::punk::netbox::system::make_rest_func ::punk::netbox::tenancy::tenants_list api/tenancy/tenants/ -verb get -body none
}
tcl::namespace::eval punk::netbox::virtualization {
namespace export {[a-z]*}
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::virtualization::virtual-machines_list
@cmd -name punk::netbox::virtualization::virtual-machines_list -help\
"virtualization_virtual-machines_list
GET request for endpoint /virtualization/virtual-machines/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
-id -type integer
-ID_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-name
-NAME_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_name_filter_help}}
-cluster -type string
-cluster_n -type string
-vcpus -type integer
-VCPUS_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-memory -type integer -help\
"Whole number"
-MEMORY_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
-disk -type integer
-DISK_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_number_filter_help}}
}\
[set ::punk::netbox::argdoc::_create_update_options]\
{
-q
-tag
}\
[set ::punk::netbox::argdoc::_tenant_options]\
[set ::punk::netbox::argdoc::_contact_options]\
{
-local_context_data
-status
-status_n
-cluster_group_id
-cluster_group_id__n
-cluster_group
-cluster_group__n
-cluster_type_id
-cluster_type_id__n
-cluster_type
-cluster_type__n
-cluster_id
-cluster_id__n
}\
[set ::punk::netbox::argdoc::_region_options]\
[set ::punk::netbox::argdoc::_site_options]\
{
-platform
-platform__n
-mac_address
-MAC_ADDRESS_FILTER -type list -minsize 2 -maxsize 2 -multiple 1 -help {${$::punk::netbox::argdoc::_string_filter_help}}
-has_primary_ip
}\
[set ::punk::netbox::argdoc::_group_options]\
[set ::punk::netbox::argdoc::_role_options]\
{
}\
[set ::punk::netbox::argdoc::_page_options]\
[set ::punk::netbox::argdoc::_CUSTOM_PARAMS]\
[set ::punk::netbox::argdoc::_RETURN_PAGEDICT]\
{
@values -min 0 -max 0
}]
::punk::netbox::system::make_rest_func ::punk::netbox::virtualization::virtual-machines_list api/virtualization/virtual-machines/ -verb get -body none
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::virtualization::virtual-machines_create
@cmd -name punk::netbox::virtualization::virtual-machines_create -help\
"virtualization_virtual-machines_create
GET request for endpoint /virtualization/virtual-machines/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 2 -max 2
id -type integer -help\
"A unique integer value identifying this virtual machine"
body -type string -help\
"JSON string"
}]
::punk::netbox::system::make_rest_func ::punk::netbox::virtualization::virtual-machines_create api/virtualization/virtual-machines/ -verb post -body required
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::virtualization::virtual-machines_delete
@cmd -name punk::netbox::virtualization::virtual-machines_delete -help\
"virtualization_virtual-machines_delete
DELETE request for endpoint /virtualization/virtual-machines/
HTTP code: 204
"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
-FORCE -default 0 -type boolean -help\
"Set to true to BULK delete all items at this endpoint"
}\
{
@values -min 0 -max 0
}]
::punk::netbox::system::make_rest_func ::punk::netbox::virtualization::virtual-machines_delete api/virtualization/virtual-machines/ -verb delete -body none
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::virtualization::virtual-machines_read
@cmd -name punk::netbox::virtualization::virtual-machines_read -help\
"virtualization_virtual-machines_read
GET request for endpoint /virtualization/virtual-machines/{id}"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 1 -max 1
id -type integer -help\
"A unique integer value identifying this virtual machine"
}]
::punk::netbox::system::make_rest_func ::punk::netbox::virtualization::virtual-machines_read api/virtualization/virtual-machines/{id}/ -verb get -body none
lappend PUNKARGS [list\
{
@dynamic
@id -id ::punk::netbox::virtualization::virtual-machines_update
@cmd -name punk::netbox::virtualization::virtual-machines_update -help\
"virtualization_virtual-machines_update
PUT request for endpoint /virtualization/virtual-machines/{id}"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${[punk::netbox::api_context_names]}}
@opts
}\
[set ::punk::netbox::argdoc::_RETURN_DICT]\
{
@values -min 2 -max 2
id -type integer -help\
"A unique integer value identifying this virtual machine"
body -type string -help\
"JSON string"
}]
::punk::netbox::system::make_rest_func ::punk::netbox::virtualization::virtual-machines_update api/virtualization/virtual-machines/{id}/ -verb put -body required
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Secondary API namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::netbox::lib {
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
tcl::namespace::path [tcl::namespace::parent]
#*** !doctools
#[subsection {Namespace punk::netbox::lib}]
#[para] Secondary functions that are part of the API
#[list_begin definitions]
#proc utility1 {p1 args} {
# #*** !doctools
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]]
# #[para]Description of utility1
# return 1
#}
#*** !doctools
#[list_end] [comment {--- end definitions namespace punk::netbox::lib ---}]
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation
# == === === === === === === === === === === === === === ===
tcl::namespace::eval punk::netbox {
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
variable PUNKARGS
variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "(package)punk::netbox"
@package -name "punk::netbox" -help\
"Package
Description"
}]
namespace eval argdoc {
#namespace for custom argument documentation
proc package_name {} {
return punk::netbox
}
proc about_topics {} {
#info commands results are returned in an arbitrary order (like array keys)
set topic_funs [info commands [namespace current]::get_topic_*]
set about_topics [list]
foreach f $topic_funs {
set tail [namespace tail $f]
lappend about_topics [string range $tail [string length get_topic_] end]
}
#Adjust this function or 'default_topics' if a different order is required
return [lsort $about_topics]
}
proc default_topics {} {return [list Description *]}
# -------------------------------------------------------------
# get_topic_ functions add more to auto-include in about topicg
# -------------------------------------------------------------
proc get_topic_Description {} {
punk::args::lib::tstr [string trim {
package punk::netbox
A library for calling netbox REST functions
} \n]
}
proc get_topic_License {} {
return "MIT"
}
proc get_topic_Version {} {
return "$::punk::netbox::version"
}
proc get_topic_Contributors {} {
set authors {{Julian Noble <julian@precisium.com.au>}}
set contributors ""
foreach a $authors {
append contributors $a \n
}
if {[string index $contributors end] eq "\n"} {
set contributors [string range $contributors 0 end-1]
}
return $contributors
}
proc get_topic_features {} {
punk::args::lib::tstr -return string {
netbox /status/ endpoint
beginnings of /ipam/ endpoints
beginnings of /virtualization/ endpoints
}
}
# -------------------------------------------------------------
}
# we re-use the argument definition from punk::args::standard_about and override some items
set overrides [dict create]
dict set overrides @id -id "::punk::netbox::about"
dict set overrides @cmd -name "punk::netbox::about"
dict set overrides @cmd -help [string trim [punk::args::lib::tstr {
About punk::netbox
}] \n]
dict set overrides topic -choices [list {*}[punk::netbox::argdoc::about_topics] *]
dict set overrides topic -choicerestricted 1
dict set overrides topic -default [punk::netbox::argdoc::default_topics] ;#if -default is present 'topic' will always appear in parsed 'values' dict
set newdef [punk::args::resolved_def -antiglobs -package_about_namespace -override $overrides ::punk::args::package::standard_about *]
lappend PUNKARGS [list $newdef]
proc about {args} {
package require punk::args
#standard_about accepts additional choices for topic - but we need to normalize any abbreviations to full topic name before passing on
set argd [punk::args::parse $args withid ::punk::netbox::about]
lassign [dict values $argd] _leaders opts values _received
punk::args::package::standard_about -package_about_namespace ::punk::netbox::argdoc {*}$opts {*}[dict get $values topic]
}
}
# end of sample 'about' function
# == === === === === === === === === === === === === === ===
# -----------------------------------------------------------------------------
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked
# -----------------------------------------------------------------------------
# variable PUNKARGS
# variable PUNKARGS_aliases
namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES\
::punk::netbox\
::punk::netbox::dcim\
::punk::netbox::ipam\
::punk::netbox::tenancy\
::punk::netbox::virtualization
}
# -----------------------------------------------------------------------------
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready
package provide punk::netbox [tcl::namespace::eval punk::netbox {
variable pkg punk::netbox
variable version
set version 999999.0a1.0
}]
return
#*** !doctools
#[manpage_end]