gabstopper / smc-python

Forcepoint Security Management Center python library:(Moved to official Forcepoint repo)
https://github.com/Forcepoint/fp-NGFW-SMC-python
Apache License 2.0
29 stars 13 forks source link

How to create "generic" objects? #55

Closed sebbbastien closed 5 years ago

sebbbastien commented 5 years ago

Hi David,

I have to create Geolocation objects.

In [23]: list(Search.objects.entry_point('geolocation'))                                                                                                                                                                                       
Out[23]: [GeolocationDynamic(name=Sainte-Tulle)]

I tried to mimic the generic_element approach with this code

In [33]: from smc.base.model import lookup_class                                                                                                                                                                                               

In [34]: lookup_class('geolocation')                                                                                                                                                                                                           
Out[34]: smc.base.model.GeolocationDynamic

In [35]: lookup_class('geolocation').update_or_create(name="Paris", city='Paris', latitude='48.8566101', longitude='2.3514992')                                                                                                                
---------------------------------------------------------------------------
ElementNotFound                           Traceback (most recent call last)
~/dev/clients/ats/env/lib/python3.7/site-packages/smc/base/model.py in get_or_create(cls, filter_key, with_status, **kwargs)
    572             try:
--> 573                 element = cls.get(kwargs.get('name'))
    574             except ElementNotFound:

~/dev/clients/ats/env/lib/python3.7/site-packages/smc/base/model.py in get(cls, name, raise_exc)
    522             raise ElementNotFound('Cannot find specified element: %s, type: '
--> 523                 '%s' % (name, cls.__name__))
    524         return element

ElementNotFound: Cannot find specified element: Paris, type: GeolocationDynamic

During handling of the above exception, another exception occurred:

CreateElementFailed                       Traceback (most recent call last)
<ipython-input-45-5832bd43052a> in <module>
----> 1 lookup_class('geolocation').update_or_create(name="Paris", city='Paris', latitude='48.8566101', longitude='2.3514992')

~/dev/clients/ats/env/lib/python3.7/site-packages/smc/base/model.py in update_or_create(cls, filter_key, with_status, **kwargs)
    639             with_status = True
    640 
--> 641         element, created = cls.get_or_create(filter_key=filter_key, with_status=True, **kwargs)
    642         if not created:
    643             for key, value in kwargs.items():

~/dev/clients/ats/env/lib/python3.7/site-packages/smc/base/model.py in get_or_create(cls, filter_key, with_status, **kwargs)
    576                     raise CreateElementFailed('%s: %r not found and this element '
    577                         'type does not have a create method.' %
--> 578                         (cls.__name__, kwargs['name']))
    579                 element = None
    580 

CreateElementFailed: GeolocationDynamic: 'Paris' not found and this element type does not have a create method.

Did I miss something? Is there a simple way to create un-implemented objects with smc-python, without writing a dedicated class? Geolocation is an "atomic" object, it does not refer to other objects unlike many others.

Best regards,

gabstopper commented 5 years ago

Elements returned with suffix 'Dynamic' are constructed dynamically and are generally considered immutable, however an objects mutability can change from SMC API version. In this case, Geolocation objects became mutable in 6.6 (btw, some versioning changes are going to be made soon to ensure pinning of smc-python vs. SMC API).

Create constructors are always unique as their base requirements are unique per element type. I just pushed a patch for Gelocation mutable elements to the dev branch, here is an example:

from smc.elements.other import Geolocation

mygeo = Geolocation.create(name='acoldplace', latitude='-90.0', longitude='120.0')
pprint(vars(mygeo.data))

# Get any user created geo objects            
for geo in Geolocation.objects.all():
    print(geo)

Signature is:

@classmethod
def create(cls, name, latitude, longitude, country_code='US', **kw)

The kwargs passed in can match the top level json kwarg if you need to add additional settings.

sebbbastien commented 5 years ago

Hi David,

It works like a charm, thanks!

Best regards,