cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1534
Views
10
Helpful
4
Replies

Json format from Cobra/ACI-toolkit query

m.papini
Level 1
Level 1

Hi  there,

I'm digging my way through the queries with Cobra SDK and I'm getting stuck on how to extract a Json formatted output from a query. This is easily done when you push a new config using toJSONStr from jsoncodec in both cobra and ACI-toolkit but I'm not sure on how this can be done when you query the actual config on a fabric. My purpose is to be able to automate Json formatted config download from a certain number of elements/tenants without using the usual GUI right click "save as". This is my query sample with Cobra (ACI-toolkit produces similar situation):

 

import cobra.mit.access
import cobra.mit.request
import cobra.mit.session
import cobra.model.fv
import cobra.model.pol
#from cobra.internal.codec.xmlcodec import toXMLStr
from cobra.internal.codec.jsoncodec import toJSONStr
from credentials import *

# set login session
session = cobra.mit.session.LoginSession(URL, LOGIN, PASSWORD)
# set object directory
moDir = cobra.mit.access.MoDirectory(session)
# submit login
moDir.login()
# filter class
cq = cobra.mit.request.ClassQuery('fvTenant')
# set subtree to full
cq.subtree = 'full'
# set property filter to tenant name
cq.propFilter = 'eq(fvTenant.name, "My_Tenant")'
# submit query
tnt = moDir.query(cq)
#print
print(toJSONStr(tnt))

Which gives the following output:

AttributeError: 'listWithTotalCount' object has no attribute 'meta'

I take it the code is obviously wrong. I've been trying with json.dumps as well for the sake of it but the outcome it is simply an empty []

Any hint would be greatly appreciated.

 

Thanks!

2 Accepted Solutions

Accepted Solutions

Derek Zhang
Cisco Employee
Cisco Employee
#print
print(toJSONStr(tnt))

---------------
Checking the objects around, it seems this is a generator of the MO objects, that we could use the iteration to list MO object.
I tried the following and it seems to work.

print([json.loads(toJSONStr(mo)) for mo in tnt])
or
for mo in tnt:
print(json.loads(toJSONStr(mo))

View solution in original post

Claudia de Luna
Spotlight
Spotlight

Hi @m.papini 

 

Typically, the query will return an object.

 

For example, with the ACI-Toolkit a tenant query like this

 

# Download all of the tenants
   tenants = ACI.Tenant.get(session)

 

gets you a list of Tenant objects like <acitoolkit.acitoolkit.Tenant object at 0x10bae8c18>,

 

print the tenant variable which is of type <class 'list'>
[<acitoolkit.acitoolkit.Tenant object at 0x10bae8c18>, <acitoolkit.acitoolkit.Tenant object at 0x10c0ef128>, <acitoolkit.acitoolkit.Tenant object at 0x10c0ef160>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d3828>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d37f0>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d37b8>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d3780>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d3748>, <acitoolkit.acitoolkit.Tenant object at 0x10c0a9320>, <acitoolkit.acitoolkit.Tenant object at 0x10c0a9390>, <acitoolkit.acitoolkit.Tenant object at 0x10c0ef198>, <acitoolkit.acitoolkit.Tenant object at 0x10c0ef1d0>]

Each of those Tenant objects has the methods below (one of which is .name).  To do this you can just use the dir method on the object.  Because you get back a list used the first element in the list (the first tenant object) and ran it through dir.

print(dir(response_list[0]))

 

lets see methods with dir:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_add_relation', '_attachments', '_check_attachment', '_check_relation', '_children', '_dedup_searchables', '_define_searchables', '_deleted', '_extract_relationships', '_generate_attributes', '_get_all_detached_relation', '_get_all_relation', '_get_all_relations_by_class', '_get_any_relation', '_get_apic_classes', '_get_children_classes', '_get_children_concrete_classes', '_get_instance_subscription_urls', '_get_name_dn_delimiters', '_get_name_from_dn', '_get_parent_class', '_get_parent_dn', '_get_parent_from_dn', '_get_starting_name_delimiter', '_get_subscription_urls', '_get_toolkit_to_apic_classmap', '_get_url_extension', '_has_any_relation', '_has_relation', '_instance_get_event', '_instance_get_subtree_faults', '_instance_has_events', '_instance_has_subtree_faults', '_instance_subscribe', '_instance_unsubscribe', '_parent', '_populate_from_attributes', '_relations', '_remove_all_relation', '_remove_attachment', '_remove_relation', '_session', '_tags', 'add_child', 'add_tag', 'attach', 'check_session', 'delete_tag', 'descr', 'detach', 'dn', 'exists', 'find', 'get', 'get_all_attached', 'get_all_attachments', 'get_attributes', 'get_child', 'get_children', 'get_deep', 'get_deep_apic_classes', 'get_dn_from_attributes', 'get_event', 'get_fault', 'get_from_json', 'get_interfaces', 'get_json', 'get_parent', 'get_searchable', 'get_table', 'get_tags', 'get_url', 'has_attachment', 'has_child', 'has_detachment', 'has_events', 'has_parent', 'has_tag', 'has_tags', 'info', 'infoList', 'is_attached', 'is_deleted', 'is_detached', 'is_interface', 'mark_as_deleted', 'mask_class_from_graphs', 'name', 'populate_children', 'push_to_apic', 'remove_child', 'remove_tag', 'set_parent', 'subscribe', 'subscribe_to_fault_instances_subtree', 'unsubscribe', 'update_db']

 

Note that one of the methods is “get_json”

 

    print(f"\nlets use the get_json method on one of the objects")
    print(tenants[0].get_json())

This gives us the JSON payload you would want to use to push updates.

 

lets use the get_json method on one of the objects:

 

{'fvTenant': {'attributes': {'name': 'infra'}, 'children': []}}

To iterate over the tenants in the list and print their name you can use the .name method:

    for tenant in tenants:
        print(tenant.name)

My suggestion is to use the API Inspector to develop your payload templates.

 

View solution in original post

4 Replies 4

Derek Zhang
Cisco Employee
Cisco Employee
#print
print(toJSONStr(tnt))

---------------
Checking the objects around, it seems this is a generator of the MO objects, that we could use the iteration to list MO object.
I tried the following and it seems to work.

print([json.loads(toJSONStr(mo)) for mo in tnt])
or
for mo in tnt:
print(json.loads(toJSONStr(mo))

Thanks Derek, the mo iteration was the bit I was missing. Nice one.

Cheers!

Claudia de Luna
Spotlight
Spotlight

Hi @m.papini 

 

Typically, the query will return an object.

 

For example, with the ACI-Toolkit a tenant query like this

 

# Download all of the tenants
   tenants = ACI.Tenant.get(session)

 

gets you a list of Tenant objects like <acitoolkit.acitoolkit.Tenant object at 0x10bae8c18>,

 

print the tenant variable which is of type <class 'list'>
[<acitoolkit.acitoolkit.Tenant object at 0x10bae8c18>, <acitoolkit.acitoolkit.Tenant object at 0x10c0ef128>, <acitoolkit.acitoolkit.Tenant object at 0x10c0ef160>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d3828>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d37f0>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d37b8>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d3780>, <acitoolkit.acitoolkit.Tenant object at 0x10c0d3748>, <acitoolkit.acitoolkit.Tenant object at 0x10c0a9320>, <acitoolkit.acitoolkit.Tenant object at 0x10c0a9390>, <acitoolkit.acitoolkit.Tenant object at 0x10c0ef198>, <acitoolkit.acitoolkit.Tenant object at 0x10c0ef1d0>]

Each of those Tenant objects has the methods below (one of which is .name).  To do this you can just use the dir method on the object.  Because you get back a list used the first element in the list (the first tenant object) and ran it through dir.

print(dir(response_list[0]))

 

lets see methods with dir:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_add_relation', '_attachments', '_check_attachment', '_check_relation', '_children', '_dedup_searchables', '_define_searchables', '_deleted', '_extract_relationships', '_generate_attributes', '_get_all_detached_relation', '_get_all_relation', '_get_all_relations_by_class', '_get_any_relation', '_get_apic_classes', '_get_children_classes', '_get_children_concrete_classes', '_get_instance_subscription_urls', '_get_name_dn_delimiters', '_get_name_from_dn', '_get_parent_class', '_get_parent_dn', '_get_parent_from_dn', '_get_starting_name_delimiter', '_get_subscription_urls', '_get_toolkit_to_apic_classmap', '_get_url_extension', '_has_any_relation', '_has_relation', '_instance_get_event', '_instance_get_subtree_faults', '_instance_has_events', '_instance_has_subtree_faults', '_instance_subscribe', '_instance_unsubscribe', '_parent', '_populate_from_attributes', '_relations', '_remove_all_relation', '_remove_attachment', '_remove_relation', '_session', '_tags', 'add_child', 'add_tag', 'attach', 'check_session', 'delete_tag', 'descr', 'detach', 'dn', 'exists', 'find', 'get', 'get_all_attached', 'get_all_attachments', 'get_attributes', 'get_child', 'get_children', 'get_deep', 'get_deep_apic_classes', 'get_dn_from_attributes', 'get_event', 'get_fault', 'get_from_json', 'get_interfaces', 'get_json', 'get_parent', 'get_searchable', 'get_table', 'get_tags', 'get_url', 'has_attachment', 'has_child', 'has_detachment', 'has_events', 'has_parent', 'has_tag', 'has_tags', 'info', 'infoList', 'is_attached', 'is_deleted', 'is_detached', 'is_interface', 'mark_as_deleted', 'mask_class_from_graphs', 'name', 'populate_children', 'push_to_apic', 'remove_child', 'remove_tag', 'set_parent', 'subscribe', 'subscribe_to_fault_instances_subtree', 'unsubscribe', 'update_db']

 

Note that one of the methods is “get_json”

 

    print(f"\nlets use the get_json method on one of the objects")
    print(tenants[0].get_json())

This gives us the JSON payload you would want to use to push updates.

 

lets use the get_json method on one of the objects:

 

{'fvTenant': {'attributes': {'name': 'infra'}, 'children': []}}

To iterate over the tenants in the list and print their name you can use the .name method:

    for tenant in tenants:
        print(tenant.name)

My suggestion is to use the API Inspector to develop your payload templates.

 

Thanks Claudia, I did run into that output using the Toolkit and with your input now I'm able to dissect that entirely, very helpful.

Thanks a million.

 

Regards,

Massimo