Add possibility to override base_path for resource operations
We currently have multiple places, where we inherit resource just to be able to request it's Details or so under different url. With 619594 a change has been introduced to improve this by having possibility to override base_path for a single resource operation. This was done only for list operations. However there are also cases when such possibility would be nice for create/update/etc operations. One example is dry-run for heat, where the endpoint receives "/preview" part. This is currently implemented by creating additional resource StackPreview with different base_path. For create it might be ok, but dry-run stack update would require another url. With this change a possibility to override base_path for individual operation on resource object is added. It can be given to proxy function, which would pass it to resource and use it during URI calculation. Change-Id: Id8c8212249cb985d2e47eb1d4fb23ebf19b3871b
This commit is contained in:
parent
841ea76fba
commit
8274409c9e
|
@ -51,7 +51,7 @@ class Keypair(resource.Resource):
|
|||
return super(Keypair, self)._consume_attrs(mapping, attrs)
|
||||
|
||||
@classmethod
|
||||
def list(cls, session, paginated=False):
|
||||
def list(cls, session, paginated=False, base_path=None):
|
||||
resp = session.get(cls.base_path,
|
||||
headers={"Accept": "application/json"})
|
||||
resp = resp.json()
|
||||
|
|
|
@ -76,7 +76,8 @@ class Limits(resource.Resource):
|
|||
absolute = resource.Body("absolute", type=AbsoluteLimits)
|
||||
rate = resource.Body("rate", type=list, list_type=RateLimit)
|
||||
|
||||
def fetch(self, session, requires_id=False, error_message=None):
|
||||
def fetch(self, session, requires_id=False, error_message=None,
|
||||
base_path=None):
|
||||
"""Get the Limits resource.
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
|
@ -88,4 +89,5 @@ class Limits(resource.Resource):
|
|||
# TODO(mordred) We shouldn't have to subclass just to declare
|
||||
# requires_id = False.
|
||||
return super(Limits, self).fetch(
|
||||
session=session, requires_id=False, error_message=error_message)
|
||||
session=session, requires_id=False, error_message=error_message,
|
||||
base_path=base_path)
|
||||
|
|
|
@ -138,7 +138,8 @@ class Server(resource.Resource, metadata.MetadataMixin, resource.TagMixin):
|
|||
#: only.
|
||||
instance_name = resource.Body('OS-EXT-SRV-ATTR:instance_name')
|
||||
|
||||
def _prepare_request(self, requires_id=True, prepend_key=True):
|
||||
def _prepare_request(self, requires_id=True, prepend_key=True,
|
||||
base_path=None):
|
||||
request = super(Server, self)._prepare_request(requires_id=requires_id,
|
||||
prepend_key=prepend_key)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class ServerIP(resource.Resource):
|
|||
|
||||
@classmethod
|
||||
def list(cls, session, paginated=False, server_id=None,
|
||||
network_label=None, **params):
|
||||
network_label=None, base_path=None, **params):
|
||||
url = cls.base_path % {"server_id": server_id}
|
||||
|
||||
if network_label is not None:
|
||||
|
|
|
@ -34,7 +34,8 @@ class User(resource.Resource):
|
|||
#: The password of the user
|
||||
password = resource.Body('password')
|
||||
|
||||
def _prepare_request(self, requires_id=True, prepend_key=True):
|
||||
def _prepare_request(self, requires_id=True, prepend_key=True,
|
||||
base_path=None):
|
||||
"""Prepare a request for the database service's create call
|
||||
|
||||
User.create calls require the resources_key.
|
||||
|
|
|
@ -43,7 +43,7 @@ class Extension(resource.Resource):
|
|||
updated_at = resource.Body('updated')
|
||||
|
||||
@classmethod
|
||||
def list(cls, session, paginated=False, **params):
|
||||
def list(cls, session, paginated=False, base_path=None, **params):
|
||||
resp = session.get(cls.base_path,
|
||||
params=params)
|
||||
resp = resp.json()
|
||||
|
|
|
@ -27,7 +27,7 @@ class Version(resource.Resource):
|
|||
updated = resource.Body('updated')
|
||||
|
||||
@classmethod
|
||||
def list(cls, session, paginated=False, **params):
|
||||
def list(cls, session, paginated=False, base_path=None, **params):
|
||||
resp = session.get(cls.base_path,
|
||||
params=params)
|
||||
resp = resp.json()
|
||||
|
|
|
@ -278,10 +278,11 @@ class Image(resource.Resource, resource.TagMixin):
|
|||
return resp.content
|
||||
|
||||
def _prepare_request(self, requires_id=None, prepend_key=False,
|
||||
patch=False):
|
||||
patch=False, base_path=None):
|
||||
request = super(Image, self)._prepare_request(requires_id=requires_id,
|
||||
prepend_key=prepend_key,
|
||||
patch=patch)
|
||||
patch=patch,
|
||||
base_path=base_path)
|
||||
if patch:
|
||||
headers = {
|
||||
'Content-Type': 'application/openstack-images-v2.1-json-patch',
|
||||
|
|
|
@ -77,8 +77,10 @@ class Secret(resource.Resource):
|
|||
#: (required if payload is encoded)
|
||||
payload_content_encoding = resource.Body('payload_content_encoding')
|
||||
|
||||
def fetch(self, session, requires_id=True, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id)
|
||||
def fetch(self, session, requires_id=True,
|
||||
base_path=None, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id,
|
||||
base_path=base_path)
|
||||
|
||||
response = session.get(request.url).json()
|
||||
|
||||
|
|
|
@ -41,9 +41,11 @@ class Quota(resource.Resource):
|
|||
#: The ID of the project this quota is associated with.
|
||||
project_id = resource.Body('project_id', alternate_id=True)
|
||||
|
||||
def _prepare_request(self, requires_id=True, prepend_key=False):
|
||||
def _prepare_request(self, requires_id=True,
|
||||
base_path=None, prepend_key=False):
|
||||
_request = super(Quota, self)._prepare_request(requires_id,
|
||||
prepend_key)
|
||||
prepend_key,
|
||||
base_path=base_path)
|
||||
if self.resource_key in _request.body:
|
||||
_body = _request.body[self.resource_key]
|
||||
else:
|
||||
|
|
|
@ -61,9 +61,10 @@ class Claim(resource.Resource):
|
|||
# Extract claim ID from location
|
||||
self.id = self.location.split("claims/")[1]
|
||||
|
||||
def create(self, session, prepend_key=False):
|
||||
def create(self, session, prepend_key=False, base_path=None):
|
||||
request = self._prepare_request(requires_id=False,
|
||||
prepend_key=prepend_key)
|
||||
prepend_key=prepend_key,
|
||||
base_path=base_path)
|
||||
headers = {
|
||||
"Client-ID": self.client_id or str(uuid.uuid4()),
|
||||
"X-PROJECT-ID": self.project_id or session.get_project_id()
|
||||
|
@ -80,8 +81,10 @@ class Claim(resource.Resource):
|
|||
|
||||
return self
|
||||
|
||||
def fetch(self, session, requires_id=True, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id)
|
||||
def fetch(self, session, requires_id=True,
|
||||
base_path=None, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id,
|
||||
base_path=base_path)
|
||||
headers = {
|
||||
"Client-ID": self.client_id or str(uuid.uuid4()),
|
||||
"X-PROJECT-ID": self.project_id or session.get_project_id()
|
||||
|
@ -94,8 +97,10 @@ class Claim(resource.Resource):
|
|||
|
||||
return self
|
||||
|
||||
def commit(self, session, prepend_key=False, has_body=False):
|
||||
request = self._prepare_request(prepend_key=prepend_key)
|
||||
def commit(self, session, prepend_key=False, has_body=False,
|
||||
base_path=None):
|
||||
request = self._prepare_request(prepend_key=prepend_key,
|
||||
base_path=base_path)
|
||||
headers = {
|
||||
"Client-ID": self.client_id or str(uuid.uuid4()),
|
||||
"X-PROJECT-ID": self.project_id or session.get_project_id()
|
||||
|
|
|
@ -67,7 +67,7 @@ class Message(resource.Resource):
|
|||
return response.json()['resources']
|
||||
|
||||
@classmethod
|
||||
def list(cls, session, paginated=True, **params):
|
||||
def list(cls, session, paginated=True, base_path=None, **params):
|
||||
"""This method is a generator which yields message objects.
|
||||
|
||||
This is almost the copy of list method of resource.Resource class.
|
||||
|
@ -107,8 +107,10 @@ class Message(resource.Resource):
|
|||
query_params["limit"] = yielded
|
||||
query_params["marker"] = new_marker
|
||||
|
||||
def fetch(self, session, requires_id=True, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id)
|
||||
def fetch(self, session, requires_id=True,
|
||||
base_path=None, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id,
|
||||
base_path=base_path)
|
||||
headers = {
|
||||
"Client-ID": self.client_id or str(uuid.uuid4()),
|
||||
"X-PROJECT-ID": self.project_id or session.get_project_id()
|
||||
|
|
|
@ -50,9 +50,10 @@ class Queue(resource.Resource):
|
|||
#: in case keystone auth is not enabled in Zaqar service.
|
||||
project_id = resource.Header("X-PROJECT-ID")
|
||||
|
||||
def create(self, session, prepend_key=True):
|
||||
def create(self, session, prepend_key=True, base_path=None):
|
||||
request = self._prepare_request(requires_id=True,
|
||||
prepend_key=prepend_key)
|
||||
prepend_key=prepend_key,
|
||||
base_path=None)
|
||||
headers = {
|
||||
"Client-ID": self.client_id or str(uuid.uuid4()),
|
||||
"X-PROJECT-ID": self.project_id or session.get_project_id()
|
||||
|
@ -65,7 +66,7 @@ class Queue(resource.Resource):
|
|||
return self
|
||||
|
||||
@classmethod
|
||||
def list(cls, session, paginated=False, **params):
|
||||
def list(cls, session, paginated=False, base_path=None, **params):
|
||||
"""This method is a generator which yields queue objects.
|
||||
|
||||
This is almost the copy of list method of resource.Resource class.
|
||||
|
@ -105,8 +106,10 @@ class Queue(resource.Resource):
|
|||
query_params["limit"] = yielded
|
||||
query_params["marker"] = new_marker
|
||||
|
||||
def fetch(self, session, requires_id=True, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id)
|
||||
def fetch(self, session, requires_id=True,
|
||||
base_path=None, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id,
|
||||
base_path=base_path)
|
||||
headers = {
|
||||
"Client-ID": self.client_id or str(uuid.uuid4()),
|
||||
"X-PROJECT-ID": self.project_id or session.get_project_id()
|
||||
|
|
|
@ -58,7 +58,7 @@ class Subscription(resource.Resource):
|
|||
#: authentication is not enabled in Zaqar service.
|
||||
project_id = resource.Header("X-PROJECT-ID")
|
||||
|
||||
def create(self, session, prepend_key=True):
|
||||
def create(self, session, prepend_key=True, base_path=None):
|
||||
request = self._prepare_request(requires_id=False,
|
||||
prepend_key=prepend_key)
|
||||
headers = {
|
||||
|
@ -73,7 +73,7 @@ class Subscription(resource.Resource):
|
|||
return self
|
||||
|
||||
@classmethod
|
||||
def list(cls, session, paginated=True, **params):
|
||||
def list(cls, session, paginated=True, base_path=None, **params):
|
||||
"""This method is a generator which yields subscription objects.
|
||||
|
||||
This is almost the copy of list method of resource.Resource class.
|
||||
|
@ -113,8 +113,10 @@ class Subscription(resource.Resource):
|
|||
query_params["limit"] = yielded
|
||||
query_params["marker"] = new_marker
|
||||
|
||||
def fetch(self, session, requires_id=True, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id)
|
||||
def fetch(self, session, requires_id=True,
|
||||
base_path=None, error_message=None):
|
||||
request = self._prepare_request(requires_id=requires_id,
|
||||
base_path=base_path)
|
||||
headers = {
|
||||
"Client-ID": self.client_id or str(uuid.uuid4()),
|
||||
"X-PROJECT-ID": self.project_id or session.get_project_id()
|
||||
|
|
|
@ -56,7 +56,8 @@ class Quota(resource.Resource):
|
|||
#: The maximum amount of security groups you can create. *Type: int*
|
||||
security_groups = resource.Body('security_group', type=int)
|
||||
|
||||
def _prepare_request(self, requires_id=True, prepend_key=False):
|
||||
def _prepare_request(self, requires_id=True, prepend_key=False,
|
||||
base_path=None):
|
||||
_request = super(Quota, self)._prepare_request(requires_id,
|
||||
prepend_key)
|
||||
if self.resource_key in _request.body:
|
||||
|
|
|
@ -109,7 +109,7 @@ class Container(_base.BaseResource):
|
|||
kwargs.setdefault('name', name)
|
||||
return Container(_synchronized=True, **kwargs)
|
||||
|
||||
def create(self, session, prepend_key=True):
|
||||
def create(self, session, prepend_key=True, base_path=None):
|
||||
"""Create a remote resource based on this instance.
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
|
@ -123,7 +123,7 @@ class Container(_base.BaseResource):
|
|||
:data:`Resource.allow_create` is not set to ``True``.
|
||||
"""
|
||||
request = self._prepare_request(
|
||||
requires_id=True, prepend_key=prepend_key)
|
||||
requires_id=True, prepend_key=prepend_key, base_path=base_path)
|
||||
response = session.put(
|
||||
request.url, json=request.body, headers=request.headers)
|
||||
|
||||
|
|
|
@ -285,8 +285,8 @@ class Object(_base.BaseResource):
|
|||
session, error_message=error_message, stream=True)
|
||||
return response.iter_content(chunk_size, decode_unicode=False)
|
||||
|
||||
def create(self, session):
|
||||
request = self._prepare_request()
|
||||
def create(self, session, base_path=None):
|
||||
request = self._prepare_request(base_path=base_path)
|
||||
request.headers['Accept'] = ''
|
||||
|
||||
response = session.put(
|
||||
|
|
|
@ -45,7 +45,8 @@ class SoftwareConfig(resource.Resource):
|
|||
#: produces.
|
||||
outputs = resource.Body('outputs')
|
||||
|
||||
def create(self, session):
|
||||
def create(self, session, base_path=None):
|
||||
# This overrides the default behavior of resource creation because
|
||||
# heat doesn't accept resource_key in its request.
|
||||
return super(SoftwareConfig, self).create(session, prepend_key=False)
|
||||
return super(SoftwareConfig, self).create(session, prepend_key=False,
|
||||
base_path=base_path)
|
||||
|
|
|
@ -49,14 +49,14 @@ class SoftwareDeployment(resource.Resource):
|
|||
#: The date and time when the software deployment resource was created.
|
||||
updated_at = resource.Body('updated_time')
|
||||
|
||||
def create(self, session):
|
||||
def create(self, session, base_path=None):
|
||||
# This overrides the default behavior of resource creation because
|
||||
# heat doesn't accept resource_key in its request.
|
||||
return super(SoftwareDeployment, self).create(
|
||||
session, prepend_key=False)
|
||||
session, prepend_key=False, base_path=base_path)
|
||||
|
||||
def commit(self, session):
|
||||
def commit(self, session, base_path=None):
|
||||
# This overrides the default behavior of resource creation because
|
||||
# heat doesn't accept resource_key in its request.
|
||||
return super(SoftwareDeployment, self).commit(
|
||||
session, prepend_key=False)
|
||||
session, prepend_key=False, base_path=base_path)
|
||||
|
|
|
@ -74,16 +74,17 @@ class Stack(resource.Resource):
|
|||
#: The ID of the user project created for this stack.
|
||||
user_project_id = resource.Body('stack_user_project_id')
|
||||
|
||||
def create(self, session):
|
||||
def create(self, session, base_path=None):
|
||||
# This overrides the default behavior of resource creation because
|
||||
# heat doesn't accept resource_key in its request.
|
||||
return super(Stack, self).create(session, prepend_key=False)
|
||||
return super(Stack, self).create(session, prepend_key=False,
|
||||
base_path=base_path)
|
||||
|
||||
def commit(self, session):
|
||||
def commit(self, session, base_path=None):
|
||||
# This overrides the default behavior of resource creation because
|
||||
# heat doesn't accept resource_key in its request.
|
||||
return super(Stack, self).commit(session, prepend_key=False,
|
||||
has_body=False)
|
||||
has_body=False, base_path=None)
|
||||
|
||||
def _action(self, session, body):
|
||||
"""Perform stack actions"""
|
||||
|
@ -94,10 +95,12 @@ class Stack(resource.Resource):
|
|||
def check(self, session):
|
||||
return self._action(session, {'check': ''})
|
||||
|
||||
def fetch(self, session, requires_id=True, error_message=None):
|
||||
def fetch(self, session, requires_id=True,
|
||||
base_path=None, error_message=None):
|
||||
stk = super(Stack, self).fetch(
|
||||
session,
|
||||
requires_id=requires_id,
|
||||
base_path=base_path,
|
||||
error_message=error_message)
|
||||
if stk and stk.status in ['DELETE_COMPLETE', 'ADOPT_COMPLETE']:
|
||||
raise exceptions.ResourceNotFound(
|
||||
|
|
|
@ -34,9 +34,9 @@ class StackFiles(resource.Resource):
|
|||
# Backwards compat
|
||||
stack_id = id
|
||||
|
||||
def fetch(self, session):
|
||||
def fetch(self, session, base_path=None):
|
||||
# The stack files response contains a map of filenames and file
|
||||
# contents.
|
||||
request = self._prepare_request(requires_id=False)
|
||||
request = self._prepare_request(requires_id=False, base_path=base_path)
|
||||
resp = session.get(request.url)
|
||||
return resp.json()
|
||||
|
|
|
@ -161,7 +161,7 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
return rv
|
||||
|
||||
@_check_resource(strict=False)
|
||||
def _update(self, resource_type, value, **attrs):
|
||||
def _update(self, resource_type, value, base_path=None, **attrs):
|
||||
"""Update a resource
|
||||
|
||||
:param resource_type: The type of resource to update.
|
||||
|
@ -169,6 +169,9 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
:param value: The resource to update. This must either be a
|
||||
:class:`~openstack.resource.Resource` or an id
|
||||
that corresponds to a resource.
|
||||
:param str base_path: Base part of the URI for updating resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
:param dict attrs: Attributes to be passed onto the
|
||||
:meth:`~openstack.resource.Resource.update`
|
||||
method to be updated. These should correspond
|
||||
|
@ -180,13 +183,16 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
:rtype: :class:`~openstack.resource.Resource`
|
||||
"""
|
||||
res = self._get_resource(resource_type, value, **attrs)
|
||||
return res.commit(self)
|
||||
return res.commit(self, base_path=base_path)
|
||||
|
||||
def _create(self, resource_type, **attrs):
|
||||
def _create(self, resource_type, base_path=None, **attrs):
|
||||
"""Create a resource from attributes
|
||||
|
||||
:param resource_type: The type of resource to create.
|
||||
:type resource_type: :class:`~openstack.resource.Resource`
|
||||
:param str base_path: Base part of the URI for creating resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
:param path_args: A dict containing arguments for forming the request
|
||||
URL, if needed.
|
||||
:param dict attrs: Attributes to be passed onto the
|
||||
|
@ -200,10 +206,11 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
:rtype: :class:`~openstack.resource.Resource`
|
||||
"""
|
||||
res = resource_type.new(**attrs)
|
||||
return res.create(self)
|
||||
return res.create(self, base_path=base_path)
|
||||
|
||||
@_check_resource(strict=False)
|
||||
def _get(self, resource_type, value=None, requires_id=True, **attrs):
|
||||
def _get(self, resource_type, value=None, requires_id=True,
|
||||
base_path=None, **attrs):
|
||||
"""Fetch a resource
|
||||
|
||||
:param resource_type: The type of resource to get.
|
||||
|
@ -211,6 +218,9 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
:param value: The value to get. Can be either the ID of a
|
||||
resource or a :class:`~openstack.resource.Resource`
|
||||
subclass.
|
||||
:param str base_path: Base part of the URI for fetching resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
:param dict attrs: Attributes to be passed onto the
|
||||
:meth:`~openstack.resource.Resource.get`
|
||||
method. These should correspond
|
||||
|
@ -224,11 +234,12 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
res = self._get_resource(resource_type, value, **attrs)
|
||||
|
||||
return res.fetch(
|
||||
self, requires_id=requires_id,
|
||||
self, requires_id=requires_id, base_path=base_path,
|
||||
error_message="No {resource_type} found for {value}".format(
|
||||
resource_type=resource_type.__name__, value=value))
|
||||
|
||||
def _list(self, resource_type, value=None, paginated=False, **attrs):
|
||||
def _list(self, resource_type, value=None,
|
||||
paginated=False, base_path=None, **attrs):
|
||||
"""List a resource
|
||||
|
||||
:param resource_type: The type of resource to delete. This should
|
||||
|
@ -241,6 +252,9 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
to be returned in one response. When set to
|
||||
``True``, the resource supports data being
|
||||
returned across multiple pages.
|
||||
:param str base_path: Base part of the URI for listing resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
:param dict attrs: Attributes to be passed onto the
|
||||
:meth:`~openstack.resource.Resource.list` method. These should
|
||||
correspond to either :class:`~openstack.resource.URI` values
|
||||
|
@ -252,9 +266,10 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
the ``resource_type``.
|
||||
"""
|
||||
res = self._get_resource(resource_type, value, **attrs)
|
||||
return res.list(self, paginated=paginated, **attrs)
|
||||
return res.list(self, paginated=paginated,
|
||||
base_path=base_path, **attrs)
|
||||
|
||||
def _head(self, resource_type, value=None, **attrs):
|
||||
def _head(self, resource_type, value=None, base_path=None, **attrs):
|
||||
"""Retrieve a resource's header
|
||||
|
||||
:param resource_type: The type of resource to retrieve.
|
||||
|
@ -263,6 +278,9 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
for. Can be either the ID of a resource,
|
||||
a :class:`~openstack.resource.Resource` subclass,
|
||||
or ``None``.
|
||||
:param str base_path: Base part of the URI for heading resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
:param dict attrs: Attributes to be passed onto the
|
||||
:meth:`~openstack.resource.Resource.head` method.
|
||||
These should correspond to
|
||||
|
@ -272,4 +290,4 @@ class Proxy(_adapter.OpenStackSDKAdapter):
|
|||
:rtype: :class:`~openstack.resource.Resource`
|
||||
"""
|
||||
res = self._get_resource(resource_type, value, **attrs)
|
||||
return res.head(self)
|
||||
return res.head(self, base_path=base_path)
|
||||
|
|
|
@ -884,7 +884,7 @@ class Resource(dict):
|
|||
return body
|
||||
|
||||
def _prepare_request(self, requires_id=None, prepend_key=False,
|
||||
patch=False):
|
||||
patch=False, base_path=None):
|
||||
"""Prepare a request to be sent to the server
|
||||
|
||||
Create operations don't require an ID, but all others do,
|
||||
|
@ -912,7 +912,9 @@ class Resource(dict):
|
|||
else:
|
||||
headers[k] = str(v)
|
||||
|
||||
uri = self.base_path % self._uri.attributes
|
||||
if base_path is None:
|
||||
base_path = self.base_path
|
||||
uri = base_path % self._uri.attributes
|
||||
if requires_id:
|
||||
if self.id is None:
|
||||
raise exceptions.InvalidRequest(
|
||||
|
@ -1047,7 +1049,7 @@ class Resource(dict):
|
|||
|
||||
return actual
|
||||
|
||||
def create(self, session, prepend_key=True):
|
||||
def create(self, session, prepend_key=True, base_path=None):
|
||||
"""Create a remote resource based on this instance.
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
|
@ -1055,7 +1057,9 @@ class Resource(dict):
|
|||
:param prepend_key: A boolean indicating whether the resource_key
|
||||
should be prepended in a resource creation
|
||||
request. Default to True.
|
||||
|
||||
:param str base_path: Base part of the URI for creating resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
:return: This :class:`Resource` instance.
|
||||
:raises: :exc:`~openstack.exceptions.MethodNotSupported` if
|
||||
:data:`Resource.allow_create` is not set to ``True``.
|
||||
|
@ -1067,13 +1071,15 @@ class Resource(dict):
|
|||
microversion = self._get_microversion_for(session, 'create')
|
||||
if self.create_method == 'PUT':
|
||||
request = self._prepare_request(requires_id=True,
|
||||
prepend_key=prepend_key)
|
||||
prepend_key=prepend_key,
|
||||
base_path=base_path)
|
||||
response = session.put(request.url,
|
||||
json=request.body, headers=request.headers,
|
||||
microversion=microversion)
|
||||
elif self.create_method == 'POST':
|
||||
request = self._prepare_request(requires_id=False,
|
||||
prepend_key=prepend_key)
|
||||
prepend_key=prepend_key,
|
||||
base_path=base_path)
|
||||
response = session.post(request.url,
|
||||
json=request.body, headers=request.headers,
|
||||
microversion=microversion)
|
||||
|
@ -1085,13 +1091,19 @@ class Resource(dict):
|
|||
self._translate_response(response)
|
||||
return self
|
||||
|
||||
def fetch(self, session, requires_id=True, error_message=None):
|
||||
def fetch(self, session, requires_id=True,
|
||||
base_path=None, error_message=None):
|
||||
"""Get a remote resource based on this instance.
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
:type session: :class:`~keystoneauth1.adapter.Adapter`
|
||||
:param boolean requires_id: A boolean indicating whether resource ID
|
||||
should be part of the requested URI.
|
||||
:param str base_path: Base part of the URI for fetching resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
:param str error_message: An Error message to be returned if
|
||||
requested object does not exist.
|
||||
:return: This :class:`Resource` instance.
|
||||
:raises: :exc:`~openstack.exceptions.MethodNotSupported` if
|
||||
:data:`Resource.allow_fetch` is not set to ``True``.
|
||||
|
@ -1101,7 +1113,8 @@ class Resource(dict):
|
|||
if not self.allow_fetch:
|
||||
raise exceptions.MethodNotSupported(self, "fetch")
|
||||
|
||||
request = self._prepare_request(requires_id=requires_id)
|
||||
request = self._prepare_request(requires_id=requires_id,
|
||||
base_path=base_path)
|
||||
session = self._get_session(session)
|
||||
microversion = self._get_microversion_for(session, 'fetch')
|
||||
response = session.get(request.url, microversion=microversion)
|
||||
|
@ -1113,11 +1126,14 @@ class Resource(dict):
|
|||
self._translate_response(response, **kwargs)
|
||||
return self
|
||||
|
||||
def head(self, session):
|
||||
def head(self, session, base_path=None):
|
||||
"""Get headers from a remote resource based on this instance.
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
:type session: :class:`~keystoneauth1.adapter.Adapter`
|
||||
:param str base_path: Base part of the URI for fetching resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
|
||||
:return: This :class:`Resource` instance.
|
||||
:raises: :exc:`~openstack.exceptions.MethodNotSupported` if
|
||||
|
@ -1128,7 +1144,7 @@ class Resource(dict):
|
|||
if not self.allow_head:
|
||||
raise exceptions.MethodNotSupported(self, "head")
|
||||
|
||||
request = self._prepare_request()
|
||||
request = self._prepare_request(base_path=base_path)
|
||||
|
||||
session = self._get_session(session)
|
||||
microversion = self._get_microversion_for(session, 'fetch')
|
||||
|
@ -1141,7 +1157,7 @@ class Resource(dict):
|
|||
return self
|
||||
|
||||
def commit(self, session, prepend_key=True, has_body=True,
|
||||
retry_on_conflict=None):
|
||||
retry_on_conflict=None, base_path=None):
|
||||
"""Commit the state of the instance to the remote resource.
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
|
@ -1152,6 +1168,9 @@ class Resource(dict):
|
|||
:param bool retry_on_conflict: Whether to enable retries on HTTP
|
||||
CONFLICT (409). Value of ``None`` leaves
|
||||
the `Adapter` defaults.
|
||||
:param str base_path: Base part of the URI for modifying resources, if
|
||||
different from
|
||||
:data:`~openstack.resource.Resource.base_path`.
|
||||
|
||||
:return: This :class:`Resource` instance.
|
||||
:raises: :exc:`~openstack.exceptions.MethodNotSupported` if
|
||||
|
@ -1173,7 +1192,9 @@ class Resource(dict):
|
|||
if self.commit_jsonpatch:
|
||||
kwargs['patch'] = True
|
||||
|
||||
request = self._prepare_request(prepend_key=prepend_key, **kwargs)
|
||||
request = self._prepare_request(prepend_key=prepend_key,
|
||||
base_path=base_path,
|
||||
**kwargs)
|
||||
session = self._get_session(session)
|
||||
|
||||
kwargs = {}
|
||||
|
|
|
@ -130,7 +130,8 @@ class TestMessageProxy(test_proxy_base.TestProxyBase):
|
|||
def test_subscription_create(self):
|
||||
self._verify("openstack.message.v2.subscription.Subscription.create",
|
||||
self.proxy.create_subscription,
|
||||
method_args=["test_queue"])
|
||||
method_args=["test_queue"],
|
||||
expected_kwargs={"base_path": None})
|
||||
|
||||
@mock.patch.object(proxy_base.Proxy, '_get_resource')
|
||||
def test_subscription_get(self, mock_get_resource):
|
||||
|
@ -175,7 +176,8 @@ class TestMessageProxy(test_proxy_base.TestProxyBase):
|
|||
def test_claim_create(self):
|
||||
self._verify("openstack.message.v2.claim.Claim.create",
|
||||
self.proxy.create_claim,
|
||||
method_args=["test_queue"])
|
||||
method_args=["test_queue"],
|
||||
expected_kwargs={"base_path": None})
|
||||
|
||||
def test_claim_get(self):
|
||||
self._verify2("openstack.proxy.Proxy._get",
|
||||
|
|
|
@ -93,7 +93,8 @@ class TestStack(base.TestCase):
|
|||
|
||||
res = sot.create(sess)
|
||||
|
||||
mock_create.assert_called_once_with(sess, prepend_key=False)
|
||||
mock_create.assert_called_once_with(sess, prepend_key=False,
|
||||
base_path=None)
|
||||
self.assertEqual(mock_create.return_value, res)
|
||||
|
||||
@mock.patch.object(resource.Resource, 'commit')
|
||||
|
@ -104,7 +105,8 @@ class TestStack(base.TestCase):
|
|||
res = sot.commit(sess)
|
||||
|
||||
mock_commit.assert_called_once_with(sess, prepend_key=False,
|
||||
has_body=False)
|
||||
has_body=False,
|
||||
base_path=None)
|
||||
self.assertEqual(mock_commit.return_value, res)
|
||||
|
||||
def test_check(self):
|
||||
|
|
|
@ -254,13 +254,22 @@ class TestProxyUpdate(base.TestCase):
|
|||
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
self.res._update.assert_called_once_with(**self.attrs)
|
||||
self.res.commit.assert_called_once_with(self.sot)
|
||||
self.res.commit.assert_called_once_with(self.sot, base_path=None)
|
||||
|
||||
def test_update_resource_override_base_path(self):
|
||||
base_path = 'dummy'
|
||||
rv = self.sot._update(UpdateableResource, self.res,
|
||||
base_path=base_path, **self.attrs)
|
||||
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
self.res._update.assert_called_once_with(**self.attrs)
|
||||
self.res.commit.assert_called_once_with(self.sot, base_path=base_path)
|
||||
|
||||
def test_update_id(self):
|
||||
rv = self.sot._update(UpdateableResource, self.fake_id, **self.attrs)
|
||||
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
self.res.commit.assert_called_once_with(self.sot)
|
||||
self.res.commit.assert_called_once_with(self.sot, base_path=None)
|
||||
|
||||
|
||||
class TestProxyCreate(base.TestCase):
|
||||
|
@ -284,7 +293,18 @@ class TestProxyCreate(base.TestCase):
|
|||
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
CreateableResource.new.assert_called_once_with(**attrs)
|
||||
self.res.create.assert_called_once_with(self.sot)
|
||||
self.res.create.assert_called_once_with(self.sot, base_path=None)
|
||||
|
||||
def test_create_attributes_override_base_path(self):
|
||||
CreateableResource.new = mock.Mock(return_value=self.res)
|
||||
|
||||
base_path = 'dummy'
|
||||
attrs = {"x": 1, "y": 2, "z": 3}
|
||||
rv = self.sot._create(CreateableResource, base_path=base_path, **attrs)
|
||||
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
CreateableResource.new.assert_called_once_with(**attrs)
|
||||
self.res.create.assert_called_once_with(self.sot, base_path=base_path)
|
||||
|
||||
|
||||
class TestProxyGet(base.TestCase):
|
||||
|
@ -309,6 +329,7 @@ class TestProxyGet(base.TestCase):
|
|||
|
||||
self.res.fetch.assert_called_with(
|
||||
self.sot, requires_id=True,
|
||||
base_path=None,
|
||||
error_message=mock.ANY)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
|
@ -318,7 +339,7 @@ class TestProxyGet(base.TestCase):
|
|||
|
||||
self.res._update.assert_called_once_with(**args)
|
||||
self.res.fetch.assert_called_with(
|
||||
self.sot, requires_id=True,
|
||||
self.sot, requires_id=True, base_path=None,
|
||||
error_message=mock.ANY)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
|
@ -327,7 +348,18 @@ class TestProxyGet(base.TestCase):
|
|||
|
||||
RetrieveableResource.new.assert_called_with(id=self.fake_id)
|
||||
self.res.fetch.assert_called_with(
|
||||
self.sot, requires_id=True,
|
||||
self.sot, requires_id=True, base_path=None,
|
||||
error_message=mock.ANY)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
def test_get_base_path(self):
|
||||
base_path = 'dummy'
|
||||
rv = self.sot._get(RetrieveableResource, self.fake_id,
|
||||
base_path=base_path)
|
||||
|
||||
RetrieveableResource.new.assert_called_with(id=self.fake_id)
|
||||
self.res.fetch.assert_called_with(
|
||||
self.sot, requires_id=True, base_path=base_path,
|
||||
error_message=mock.ANY)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
|
@ -354,12 +386,13 @@ class TestProxyList(base.TestCase):
|
|||
ListableResource.list = mock.Mock()
|
||||
ListableResource.list.return_value = self.fake_response
|
||||
|
||||
def _test_list(self, paginated):
|
||||
rv = self.sot._list(ListableResource, paginated=paginated, **self.args)
|
||||
def _test_list(self, paginated, base_path=None):
|
||||
rv = self.sot._list(ListableResource, paginated=paginated,
|
||||
base_path=base_path, **self.args)
|
||||
|
||||
self.assertEqual(self.fake_response, rv)
|
||||
ListableResource.list.assert_called_once_with(
|
||||
self.sot, paginated=paginated, **self.args)
|
||||
self.sot, paginated=paginated, base_path=base_path, **self.args)
|
||||
|
||||
def test_list_paginated(self):
|
||||
self._test_list(True)
|
||||
|
@ -367,6 +400,9 @@ class TestProxyList(base.TestCase):
|
|||
def test_list_non_paginated(self):
|
||||
self._test_list(False)
|
||||
|
||||
def test_list_override_base_path(self):
|
||||
self._test_list(False, base_path='dummy')
|
||||
|
||||
|
||||
class TestProxyHead(base.TestCase):
|
||||
|
||||
|
@ -388,12 +424,19 @@ class TestProxyHead(base.TestCase):
|
|||
def test_head_resource(self):
|
||||
rv = self.sot._head(HeadableResource, self.res)
|
||||
|
||||
self.res.head.assert_called_with(self.sot)
|
||||
self.res.head.assert_called_with(self.sot, base_path=None)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
def test_head_resource_base_path(self):
|
||||
base_path = 'dummy'
|
||||
rv = self.sot._head(HeadableResource, self.res, base_path=base_path)
|
||||
|
||||
self.res.head.assert_called_with(self.sot, base_path=base_path)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
def test_head_id(self):
|
||||
rv = self.sot._head(HeadableResource, self.fake_id)
|
||||
|
||||
HeadableResource.new.assert_called_with(id=self.fake_id)
|
||||
self.res.head.assert_called_with(self.sot)
|
||||
self.res.head.assert_called_with(self.sot, base_path=None)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
|
|
@ -76,7 +76,17 @@ class TestProxyBase(base.TestCase):
|
|||
else:
|
||||
self.assertEqual(expected_result, test_method(*method_args,
|
||||
**method_kwargs))
|
||||
mocked.assert_called_with(*expected_args, **expected_kwargs)
|
||||
# Check how the mock was called in detail
|
||||
(called_args, called_kwargs) = mocked.call_args
|
||||
self.assertEqual(list(called_args), expected_args)
|
||||
base_path = expected_kwargs.get('base_path', None)
|
||||
# NOTE(gtema): if base_path is not in epected_kwargs or empty
|
||||
# exclude it from the comparison, since some methods might
|
||||
# still invoke method with None value
|
||||
if not base_path:
|
||||
expected_kwargs.pop('base_path', None)
|
||||
called_kwargs.pop('base_path', None)
|
||||
self.assertDictEqual(called_kwargs, expected_kwargs)
|
||||
else:
|
||||
self.assertEqual(expected_result, test_method())
|
||||
mocked.assert_called_with(test_method.__self__)
|
||||
|
@ -87,7 +97,9 @@ class TestProxyBase(base.TestCase):
|
|||
the_kwargs = {"x": 1, "y": 2, "z": 3}
|
||||
method_kwargs = kwargs.pop("method_kwargs", the_kwargs)
|
||||
expected_args = [resource_type]
|
||||
expected_kwargs = kwargs.pop("expected_kwargs", the_kwargs)
|
||||
# Default the_kwargs should be copied, since we might need to extend it
|
||||
expected_kwargs = kwargs.pop("expected_kwargs", the_kwargs.copy())
|
||||
expected_kwargs["base_path"] = kwargs.pop("base_path", None)
|
||||
|
||||
self._verify2(mock_method, test_method,
|
||||
expected_result=expected_result,
|
||||
|
@ -147,6 +159,7 @@ class TestProxyBase(base.TestCase):
|
|||
proxy._get(resource_type)
|
||||
res.fetch.assert_called_once_with(
|
||||
proxy, requires_id=True,
|
||||
base_path=None,
|
||||
error_message=mock.ANY)
|
||||
|
||||
def verify_head(self, test_method, resource_type,
|
||||
|
@ -216,7 +229,8 @@ class TestProxyBase(base.TestCase):
|
|||
method_kwargs = kwargs.pop("method_kwargs", {})
|
||||
method_kwargs.update({"x": 1, "y": 2, "z": 3})
|
||||
expected_args = kwargs.pop("expected_args", ["resource_or_id"])
|
||||
expected_kwargs = method_kwargs.copy()
|
||||
expected_kwargs = kwargs.pop("expected_kwargs", method_kwargs.copy())
|
||||
expected_kwargs["base_path"] = kwargs.pop("base_path", None)
|
||||
|
||||
self._add_path_args_for_verify(path_args, method_args, expected_kwargs,
|
||||
value=value)
|
||||
|
|
|
@ -1076,16 +1076,18 @@ class TestResourceActions(base.TestCase):
|
|||
self.session.get_endpoint_data.return_value = self.endpoint_data
|
||||
|
||||
def _test_create(self, cls, requires_id=False, prepend_key=False,
|
||||
microversion=None):
|
||||
microversion=None, base_path=None):
|
||||
id = "id" if requires_id else None
|
||||
sot = cls(id=id)
|
||||
sot._prepare_request = mock.Mock(return_value=self.request)
|
||||
sot._translate_response = mock.Mock()
|
||||
|
||||
result = sot.create(self.session, prepend_key=prepend_key)
|
||||
result = sot.create(self.session, prepend_key=prepend_key,
|
||||
base_path=base_path)
|
||||
|
||||
sot._prepare_request.assert_called_once_with(
|
||||
requires_id=requires_id, prepend_key=prepend_key)
|
||||
requires_id=requires_id, prepend_key=prepend_key,
|
||||
base_path=base_path)
|
||||
if requires_id:
|
||||
self.session.put.assert_called_once_with(
|
||||
self.request.url,
|
||||
|
@ -1130,10 +1132,21 @@ class TestResourceActions(base.TestCase):
|
|||
|
||||
self._test_create(Test, requires_id=False, prepend_key=True)
|
||||
|
||||
def test_post_create_base_path(self):
|
||||
class Test(resource.Resource):
|
||||
service = self.service_name
|
||||
base_path = self.base_path
|
||||
allow_create = True
|
||||
create_method = 'POST'
|
||||
|
||||
self._test_create(Test, requires_id=False, prepend_key=True,
|
||||
base_path='dummy')
|
||||
|
||||
def test_fetch(self):
|
||||
result = self.sot.fetch(self.session)
|
||||
|
||||
self.sot._prepare_request.assert_called_once_with(requires_id=True)
|
||||
self.sot._prepare_request.assert_called_once_with(
|
||||
requires_id=True, base_path=None)
|
||||
self.session.get.assert_called_once_with(
|
||||
self.request.url, microversion=None)
|
||||
|
||||
|
@ -1154,7 +1167,8 @@ class TestResourceActions(base.TestCase):
|
|||
|
||||
result = sot.fetch(self.session)
|
||||
|
||||
sot._prepare_request.assert_called_once_with(requires_id=True)
|
||||
sot._prepare_request.assert_called_once_with(
|
||||
requires_id=True, base_path=None)
|
||||
self.session.get.assert_called_once_with(
|
||||
self.request.url, microversion='1.42')
|
||||
|
||||
|
@ -1165,7 +1179,20 @@ class TestResourceActions(base.TestCase):
|
|||
def test_fetch_not_requires_id(self):
|
||||
result = self.sot.fetch(self.session, False)
|
||||
|
||||
self.sot._prepare_request.assert_called_once_with(requires_id=False)
|
||||
self.sot._prepare_request.assert_called_once_with(
|
||||
requires_id=False, base_path=None)
|
||||
self.session.get.assert_called_once_with(
|
||||
self.request.url, microversion=None)
|
||||
|
||||
self.sot._translate_response.assert_called_once_with(self.response)
|
||||
self.assertEqual(result, self.sot)
|
||||
|
||||
def test_fetch_base_path(self):
|
||||
result = self.sot.fetch(self.session, False, base_path='dummy')
|
||||
|
||||
self.sot._prepare_request.assert_called_once_with(
|
||||
requires_id=False,
|
||||
base_path='dummy')
|
||||
self.session.get.assert_called_once_with(
|
||||
self.request.url, microversion=None)
|
||||
|
||||
|
@ -1175,7 +1202,21 @@ class TestResourceActions(base.TestCase):
|
|||
def test_head(self):
|
||||
result = self.sot.head(self.session)
|
||||
|
||||
self.sot._prepare_request.assert_called_once_with()
|
||||
self.sot._prepare_request.assert_called_once_with(base_path=None)
|
||||
self.session.head.assert_called_once_with(
|
||||
self.request.url,
|
||||
headers={"Accept": ""},
|
||||
microversion=None)
|
||||
|
||||
self.assertIsNone(self.sot.microversion)
|
||||
self.sot._translate_response.assert_called_once_with(
|
||||
self.response, has_body=False)
|
||||
self.assertEqual(result, self.sot)
|
||||
|
||||
def test_head_base_path(self):
|
||||
result = self.sot.head(self.session, base_path='dummy')
|
||||
|
||||
self.sot._prepare_request.assert_called_once_with(base_path='dummy')
|
||||
self.session.head.assert_called_once_with(
|
||||
self.request.url,
|
||||
headers={"Accept": ""},
|
||||
|
@ -1199,7 +1240,7 @@ class TestResourceActions(base.TestCase):
|
|||
|
||||
result = sot.head(self.session)
|
||||
|
||||
sot._prepare_request.assert_called_once_with()
|
||||
sot._prepare_request.assert_called_once_with(base_path=None)
|
||||
self.session.head.assert_called_once_with(
|
||||
self.request.url,
|
||||
headers={"Accept": ""},
|
||||
|
@ -1212,7 +1253,7 @@ class TestResourceActions(base.TestCase):
|
|||
|
||||
def _test_commit(self, commit_method='PUT', prepend_key=True,
|
||||
has_body=True, microversion=None,
|
||||
commit_args=None, expected_args=None):
|
||||
commit_args=None, expected_args=None, base_path=None):
|
||||
self.sot.commit_method = commit_method
|
||||
|
||||
# Need to make sot look dirty so we can attempt an update
|
||||
|
@ -1220,10 +1261,11 @@ class TestResourceActions(base.TestCase):
|
|||
self.sot._body.dirty = mock.Mock(return_value={"x": "y"})
|
||||
|
||||
self.sot.commit(self.session, prepend_key=prepend_key,
|
||||
has_body=has_body, **(commit_args or {}))
|
||||
has_body=has_body, base_path=base_path,
|
||||
**(commit_args or {}))
|
||||
|
||||
self.sot._prepare_request.assert_called_once_with(
|
||||
prepend_key=prepend_key)
|
||||
prepend_key=prepend_key, base_path=base_path)
|
||||
|
||||
if commit_method == 'PATCH':
|
||||
self.session.patch.assert_called_once_with(
|
||||
|
@ -1252,6 +1294,10 @@ class TestResourceActions(base.TestCase):
|
|||
self._test_commit(
|
||||
commit_method='PATCH', prepend_key=False, has_body=False)
|
||||
|
||||
def test_commit_base_path(self):
|
||||
self._test_commit(commit_method='PUT', prepend_key=True, has_body=True,
|
||||
base_path='dummy')
|
||||
|
||||
def test_commit_patch_retry_on_conflict(self):
|
||||
self._test_commit(
|
||||
commit_method='PATCH',
|
||||
|
|
|
@ -50,9 +50,10 @@ class Execution(resource.Resource):
|
|||
#: The time at which the Execution was updated
|
||||
updated_at = resource.Body("updated_at")
|
||||
|
||||
def create(self, session, prepend_key=True):
|
||||
def create(self, session, prepend_key=True, base_path=None):
|
||||
request = self._prepare_request(requires_id=False,
|
||||
prepend_key=prepend_key)
|
||||
prepend_key=prepend_key,
|
||||
base_path=base_path)
|
||||
|
||||
request_body = request.body["execution"]
|
||||
response = session.post(request.url,
|
||||
|
|
|
@ -46,9 +46,10 @@ class Workflow(resource.Resource):
|
|||
#: The time at which the workflow was created
|
||||
updated_at = resource.Body("updated_at")
|
||||
|
||||
def create(self, session, prepend_key=True):
|
||||
def create(self, session, prepend_key=True, base_path=None):
|
||||
request = self._prepare_request(requires_id=False,
|
||||
prepend_key=prepend_key)
|
||||
prepend_key=prepend_key,
|
||||
base_path=base_path)
|
||||
|
||||
headers = {
|
||||
"Content-Type": 'text/plain'
|
||||
|
|
Loading…
Reference in New Issue