For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Python script for updating data group

Problem this snippet solves:

Updating data group via Python. From the article: Routing HTTP by request headers

Currently when you need to update a data group via iControl REST it requires you to retrieve a copy of all of the records, make your changes, and then re-submit all the records to make any changes. The following Python script takes care of the process of extracting all of the records, turning them into a dictionary, and then allowing the data group to be updated by passing a dictionary.

How to use this snippet:

This code can be imported as a class or run from the command-line. From the command-line:

% ./cgp.py add www.mycompany.example 10.10.1.11:80
added: www.mycompany.example
% ./cgp.py get www.mycompany.example
www.mycompany.example: 10.10.1.11:80
% ./cgp.py update www.mycompany.example 10.10.1.11:8000
updated: www.mycompany.example
% ./cgp.py del www.mycompany.example
deleted: www.mycompany.example

From code

from cgp import CGP
BIGIP_ADDRESS = '[BIGIP MGMT HOST]'
BIGIP_USER = '[admin user]'
BIGIP_PASS = '[admin password]'

DATA_GROUP = '~Common~[data-group name]'
cgp = CGP(BIGIP_ADDRESS, BIGIP_USER, BIGIP_PASS)
# get record
data =  cgp.get_data_group(DATA_GROUP)

# add record
data['www.mycompany.example'] = '10.10.1.10:80'
cgp.set_data_group(DATA_GROUP, data)

# update record
data =  cgp.get_data_group(DATA_GROUP)
data['www.mycompany.example'] = '10.10.1.10:80'
cgp.set_data_group(DATA_GROUP, data)

# delete record
data =  cgp.get_data_group(DATA_GROUP)
del data['www.mycompany.example']
cgp.set_data_group(DATA_GROUP, data)

Code :

#!/usr/bin/python
#
# Chen Gateway Protocol
#
# Example of using iControl REST
# From: https://devcentral.f5.com/s/articles/routing-http-by-request-headers
#
# Requires iControl REST > 11.5.0
#
# The following script allows one to dynamically update a data-group via
# iControl REST
#
import requests
import json

BIGIP_ADDRESS = '[BIGIP MGMT HOST]'
BIGIP_USER = '[admin user]'
BIGIP_PASS = '[admin password]'

DATA_GROUP = '~Common~[data-group name]'

class CGP(object):
    def __init__(self, host, user, passwd):
        self.host = host
        self.user = user
        self.passwd = passwd
        self.mgmt_url = "https://%s/mgmt/tm" %(host)

        self.session = requests.session()
        self.session.auth = (user, passwd)
        self.session.verify = False
        self.session.headers.update({'Content-Type':'application/json'})

    def get_data_group(self, datagroup):
        req_url = "%s/ltm/data-group/internal/%s" %(self.mgmt_url, datagroup)
        req = self.session.get(req_url)
        return dict([(a['name'],a['data']) for a in req.json()['records']])
        "return contents of data-group as dictionary"

    def set_data_group(self, datagroup, data):
        req_url = "%s/ltm/data-group/internal/%s" %(self.mgmt_url, datagroup)
        records = {'records': [{'data':r[1],'name':r[0]} for r in  data.items()]}
        req = self.session.put(req_url,data = json.dumps(records) )
        "update contents of data-group as dictionary"
        

if __name__ == "__main__":
    import argparse
    import sys
    parser = argparse.ArgumentParser()
    parser.add_argument('action')
    parser.add_argument('host_header')
    parser.add_argument('node_ip_port',nargs='?')
    args = parser.parse_args()

    cgp = CGP(BIGIP_ADDRESS, BIGIP_USER, BIGIP_PASS)
    data =  cgp.get_data_group(DATA_GROUP)
    if args.action == 'del':
        if args.host_header in data:        
            del data[args.host_header]
            print "deleted:", args.host_header
        else:
            print "error: %s does not exist" %(args.host_header)
            sys.exit(1)
    elif args.action == 'add':
        if args.host_header in data:
            print "error: %s already exists" %(args.host_header)
            sys.exit(1)
        else:
            data[args.host_header] = args.node_ip_port
            print "added: %s" %(args.host_header)
    elif args.action == 'update':
        if args.host_header in data:        
            data[args.host_header] = args.node_ip_port
            print "updated:", args.host_header
        else:
            print "error: %s does not exist" %(args.host_header)
            sys.exit(1)
    elif args.action == 'get':
        print "%s: %s" %(args.host_header,data.get(args.host_header,"DOES NOT EXIST"))
    cgp.set_data_group(DATA_GROUP, data)

Tested this on version:

11.5
Updated Jun 06, 2023
Version 2.0

5 Comments

  • it needs to replace all values in the datagroup when add/delete/update? any other better way?
  • Robert, I'm not aware of a method to perform an incremental update of a datagroup at this time. There was a similar question on DevCentral: https://devcentral.f5.com/s/feed/0D51T00006i7Y1FSAU
  • thanks,Eric I have completed my python version yeah, there is no way to perform an incremental update of a datagroup
  • why i got a problem which said "keyerror:'records'"?how can i resolve the question? tks