These scripts demonstrate the template programmer API on Cisco DNA Center. The scripts assume the templates have been setup on Cisco DNA center in advance.
The scripts are educational to illustrate the payload and API calls.
The script needs a DNAC to communicate to via a config file (dnac_config.py) or environmnent variables - (DNAC, DNAC_USER, DNAC_PASSWORD).
Run the script without argumnents to get a list of templates.
$ ./template.py
Available Templates:
https://10.66.104.121:443/api/v1/template-programmer/template
Adam/int-vlan
Adam/interface-des
DB/prefix
Onboarding Configuration/9300
Onboarding Configuration/advanced
Onboarding Configuration/basic
To find out the parameters and other attributes of a template, run the script with the --template option The script automatically gets the latest version of the template. It shows you the paramaters required ("vlan" and "interface")
$ ./template.py --template Adam/int-vlan
Looking for: Adam/int-vlan
https://10.66.104.121:443/api/v1/template-programmer/template
TemplateId: 78742a98-7a8b-435a-a2f8-284a1f940df0 Version: 9
https://10.66.104.121:443/api/v1/template-programmer/template/78742a98-7a8b-435a-a2f8-284a1f940df0
Showing Template Body:
interface $interface
switchport access vlan $vlan
Required Parameters for template body: {"vlan":"","interface":""}
Then use the --device and --params options to apply a template to a device.
This output is quite verbose as the API calls are shown in detail.
$ ./template.py --template Adam/int-vlan --device 10.10.14.4 --params '{"vlan":"20","interface":"gig1/0/22"}'
Looking for: Adam/int-vlan
https://10.66.104.121:443/api/v1/template-programmer/template
TemplateId: 78742a98-7a8b-435a-a2f8-284a1f940df0 Version: 9
<SNIP>
If a template is re-applied with the same parameters, then an error is returned as DNAC will not reapply the same template by default.
to force the template to be reapplied, use the --force option
$ ./template.py --template Adam/int-vlan --device 10.10.14.4 --params '{"vlan":"20","interface":"gig1/0/22"}' --force
Looking for: Adam/int-vlan
https://10.66.104.121:443/api/v1/template-programmer/template
TemplateId: 78742a98-7a8b-435a-a2f8-284a1f940df0 Version: 9
<SNIP>
I also started to work on the bulk application of a template to a set of devices. Use the --bulkfile option. This is a csv file with a list of device_ip and variables for the given template
The following is an exmaple where the template has two varaibles, "do" and "ip". "device_ip" is fixed and the ip addreess of the target
device_ip,do,ip
10.10.15.100,1,10.10.10.250
10.10.50.2,1,10.10.10.251
./template.py --template adam/simple --bulkfile work_files/test.csv
Looking for: adam/simple
https://10.66.104.121:443/dna/intent/api/v1/template-programmer/template
TemplateId: d26cc12d-27f3-4fd2-97cd-63f32b85e889 Version: 2
<snip>
Response:
Deployment of template:adam/simple(v2) (id:e7301391-cc86-47ae-942d-ee625dde15ea)
10.10.50.2:SUCCESS:Provisioning success for template simple
10.10.15.100:SUCCESS:Provisioning success for template simple
Sometimes it is necessary to supply series of values for a set of predefined variables in Jinja2 a template. We can have a '.csv' or a '.json' formatted source file that we can have the template iterate over for each of those variables.
Sample 'paramsfile.csv':
SITE_CODE,DESCRIPTION
CAN01,CDN_SITE_01
CAN02,CDN_SITE_02
CAN03,CDN_SITE_03
And Jinja2 Template hosted on DNAC (you will find it in 'work_files' dir in .json format which you can import int DNAC, 'WLC9800-DayN-Provisioning' project for purposes of this example):
{% SET SITE_CODE_LIST = SITE_CODE %}
{% SET DESCRIPTION_LIST = DESCRIPTION %}
{% FOR ITEM in SITE_CODE_LIST %}
{% SET SITE = SITE_CODE_LIST[loop.index-1] %}
{% SET DESCRIPTION = DESCRIPTION_LIST[loop.index-1] %}
wireless profile flex FP_{{SITE}}
acl-policy CAPTIVE_PORTAL_REDIRECT
central-webauth
no arp-caching
no local-auth ap radius
native-vlan-id 2
vlan-name data
acl Flex_Profile_Allow_All
vlan-id 10
vlan-name byod
acl Flex_Profile_Allow_All
vlan-id 20
vlan-name guest
acl Flex_Profile_Allow_All
vlan-id 30
wireless tag site ST_{{SITE}}
ap-profile MyApProfile
description {{DESCRIPTION}}
no local-site
flex-profile FP_{{SITE}}
{% ENDFOR %}
J2 template above accepts two lists of variables, and creates a nested set of configlets for each row of values in the supplied '.csv' or '.json' paramsfile
./template.py --template WLC9800-DayN-Provisioning/Guest-Wireless-Tag-Profile --device 10.85.54.99 --preview --force --paramsfile 'work_files/paramsfile.csv'
or
./template.py --template WLC9800-DayN-Provisioning/Guest-Wireless-Tag-Profile --device 10.85.54.99 --preview --force --paramsfile 'work_files/paramsfile.json'
with output
...
{% SET SITE_CODE_LIST = SITE_CODE %}
{% SET DESCRIPTION_LIST = DESCRIPTION %}
{% FOR ITEM in SITE_CODE_LIST %}
{% SET SITE = SITE_CODE_LIST[loop.index-1] %}
{% SET DESCRIPTION = DESCRIPTION_LIST[loop.index-1] %}
wireless profile flex FP_{{SITE}}
acl-policy CAPTIVE_PORTAL_REDIRECT
central-webauth
no arp-caching
no local-auth ap radius
native-vlan-id 2
vlan-name data
acl Flex_Profile_Allow_All
vlan-id 10
vlan-name byod
acl Flex_Profile_Allow_All
vlan-id 20
vlan-name guest
acl Flex_Profile_Allow_All
vlan-id 30
wireless tag site ST_{{SITE}}
ap-profile MyApProfile
description {{DESCRIPTION}}
no local-site
flex-profile FP_{{SITE}}
{% ENDFOR %}
Required Parameters for template body: {"SITE_CODE":"","SITE":"","DESCRIPTION":""}
Bindings []
Previewing template
wireless profile flex FP_CAN01
acl-policy CAPTIVE_PORTAL_REDIRECT
central-webauth
no arp-caching
no local-auth ap radius
native-vlan-id 2
vlan-name data
acl Flex_Profile_Allow_All
vlan-id 10
vlan-name byod
acl Flex_Profile_Allow_All
vlan-id 20
vlan-name guest
acl Flex_Profile_Allow_All
vlan-id 30
wireless tag site ST_CAN01
ap-profile MyApProfile
description CDN_SITE_01
no local-site
flex-profile FP_CAN01
wireless profile flex FP_CAN02
acl-policy CAPTIVE_PORTAL_REDIRECT
central-webauth
no arp-caching
no local-auth ap radius
native-vlan-id 2
vlan-name data
acl Flex_Profile_Allow_All
vlan-id 10
vlan-name byod
acl Flex_Profile_Allow_All
vlan-id 20
vlan-name guest
acl Flex_Profile_Allow_All
vlan-id 30
wireless tag site ST_CAN02
ap-profile MyApProfile
description CDN_SITE_02
no local-site
flex-profile FP_CAN02
wireless profile flex FP_CAN03
acl-policy CAPTIVE_PORTAL_REDIRECT
central-webauth
no arp-caching
no local-auth ap radius
native-vlan-id 2
vlan-name data
acl Flex_Profile_Allow_All
vlan-id 10
vlan-name byod
acl Flex_Profile_Allow_All
vlan-id 20
vlan-name guest
acl Flex_Profile_Allow_All
vlan-id 30
wireless tag site ST_CAN03
ap-profile MyApProfile
description CDN_SITE_03
no local-site
flex-profile FP_CAN03
Executing template on:10.85.54.99, with Params:{"SITE_CODE": ["CAN01", "CAN02", "CAN03"], "DESCRIPTION": ["CDN_SITE_01", "CDN_SITE_02", "CDN_SITE_03"]}
...
Response:
{
"deploymentId": "458e81b1-7095-402b-b8cb-735119543e2c",
"templateName": "Guest-Wireless-Tag-Profile",
"templateVersion": "2",
"projectName": "WLC9800-DayN-Provisioning",
"status": "SUCCESS",
"startTime": "22:44:01 19/01/2021",
"endTime": "22:44:38 19/01/2021",
"duration": "0 minutes 36 seconds",
"devices": [
{
"deviceId": "b57b4ca1-4b7c-4e07-bafc-f60b4b6d163d",
"name": "",
"status": "SUCCESS",
"detailedStatusMessage": "Provisioning success for template Guest-Wireless-Tag-Profile",
"startTime": "22:44:01 19/01/2021",
"endTime": "22:44:38 19/01/2021",
"ipAddress": "b57b4ca1-4b7c-4e07-bafc-f60b4b6d163d",
"identifier": "b57b4ca1-4b7c-4e07-bafc-f60b4b6d163d",
"targetType": "MANAGED_DEVICE_IP",
"duration": "0 minutes 36 seconds"
}
]
}