8484from f5 .bigip .mixins import LazyAttributeMixin
8585from f5 .bigip .mixins import ToDictMixin
8686from f5 .sdk_exception import F5SDKError
87+ from f5 .sdk_exception import UnsupportedMethod
8788from requests .exceptions import HTTPError
8889
8990
@@ -389,7 +390,6 @@ class ResourceBase(PathElement, ToDictMixin):
389390 This can be shortened to just the last line:
390391
391392 .. code-block:: python
392-
393393 nat1 = bigip.ltm.nats.nat.create('Foo', 'Bar', '0.1.2.3', '1.2.3.4')
394394
395395 Critically this enforces a convention relating device published uris to
@@ -531,6 +531,31 @@ def delete(self, **kwargs):
531531 error_message = "Only Resources support 'delete'."
532532 raise InvalidResource (error_message )
533533
534+ def _stamp_out_core (self ):
535+ container = self ._meta_data ['container' ]
536+ core = self .__class__ .__new__ (self .__class__ )
537+ core .__init__ (container )
538+ return core
539+
540+ def _produce_instance (self , response ):
541+ '''Generate a new self, which is an instance of the self.'''
542+ new_instance = self ._stamp_out_core ()
543+ # Post-process the response
544+ new_instance ._local_update (response .json ())
545+
546+ if new_instance .kind != new_instance ._meta_data ['required_json_kind' ] \
547+ and new_instance .kind != "tm:transaction:commandsstate" :
548+ error_message = "For instances of type '%r' the corresponding" \
549+ " kind must be '%r' but creation returned JSON with kind: %r" \
550+ % (new_instance .__class__ .__name__ ,
551+ new_instance ._meta_data ['required_json_kind' ],
552+ new_instance .kind )
553+ raise KindTypeMismatch (error_message )
554+
555+ # Update the object to have the correct functional uri.
556+ new_instance ._activate_URI (new_instance .selfLink )
557+ return new_instance
558+
534559
535560class OrganizingCollection (ResourceBase ):
536561 """Base class for objects that collect resources under them.
@@ -737,21 +762,8 @@ def _create(self, **kwargs):
737762 # Invoke the REST operation on the device.
738763 response = session .post (_create_uri , json = kwargs , ** requests_params )
739764
740- # Post-process the response
741- self ._local_update (response .json ())
742-
743- if self .kind != self ._meta_data ['required_json_kind' ] \
744- and self .kind != "tm:transaction:commandsstate" :
745- error_message = "For instances of type '%r' the corresponding" \
746- " kind must be '%r' but creation returned JSON with kind: %r" \
747- % (self .__class__ .__name__ ,
748- self ._meta_data ['required_json_kind' ],
749- self .kind )
750- raise KindTypeMismatch (error_message )
751-
752- # Update the object to have the correct functional uri.
753- self ._activate_URI (self .selfLink )
754- return self
765+ # Make new instance of self
766+ return self ._produce_instance (response )
755767
756768 def create (self , ** kwargs ):
757769 """Create the resource on the BIG-IP®.
@@ -781,8 +793,7 @@ def create(self, **kwargs):
781793 configuration and state on the BIG-IP®.
782794
783795 """
784- self ._create (** kwargs )
785- return self
796+ return self ._create (** kwargs )
786797
787798 def _load (self , ** kwargs ):
788799 """wrapped with load, override that in a subclass to customize"""
@@ -798,9 +809,8 @@ def _load(self, **kwargs):
798809 base_uri = self ._meta_data ['container' ]._meta_data ['uri' ]
799810 kwargs .update (requests_params )
800811 response = refresh_session .get (base_uri , ** kwargs )
801- self ._local_update (response .json ())
802- self ._activate_URI (self .selfLink )
803- return self
812+ # Make new instance of self
813+ return self ._produce_instance (response )
804814
805815 def load (self , ** kwargs ):
806816 """Load an already configured service into this instance.
@@ -819,12 +829,12 @@ def load(self, **kwargs):
819829 be handled according to that API. THIS IS HOW TO PASS QUERY-ARGS!
820830 :returns: a Resource Instance (with a populated _meta_data['uri'])
821831 """
822- self ._load (** kwargs )
823- return self
832+ return self ._load (** kwargs )
824833
825834 def _delete (self , ** kwargs ):
826835 """wrapped with delete, override that in a subclass to customize """
827836 requests_params = self ._handle_requests_params (kwargs )
837+
828838 delete_uri = self ._meta_data ['uri' ]
829839 session = self ._meta_data ['bigip' ]._meta_data ['icr_session' ]
830840
@@ -887,3 +897,37 @@ def exists(self, **kwargs):
887897 else :
888898 raise
889899 return True
900+
901+
902+ class UnnamedResource (ResourceBase ):
903+ '''This makes a resource object work if there is no name.
904+
905+ These objects do not support create or delete and are often found
906+ as Resources that are under an organizing collection. For example
907+ the `mgmt/tm/sys/global-settings` is one of these and has a kind of
908+ `tm:sys:global-settings:global-settingsstate` and the URI does not
909+ match the kind.
910+ '''
911+
912+ def create (self , ** kwargs ):
913+ '''Create is not supported for unnamed resources
914+
915+ :raises: UnsupportedOperation
916+ '''
917+ raise UnsupportedMethod (
918+ "%s does not support the create method" % self .__class__ .__name__
919+ )
920+
921+ def delete (self , ** kwargs ):
922+ '''Delete is not supported for unnamed resources
923+
924+ :raises: UnsupportedOperation
925+ '''
926+ raise UnsupportedMethod (
927+ "%s does not support the delete method" % self .__class__ .__name__
928+ )
929+
930+ def load (self , ** kwargs ):
931+ newinst = self ._stamp_out_core ()
932+ newinst ._refresh (** kwargs )
933+ return newinst
0 commit comments