renamed hosts to services
This commit is contained in:
@@ -4,4 +4,4 @@ from cdn.provider import base
|
||||
|
||||
# Hoist classes into package namespace
|
||||
CDNProviderBase = base.CDNProviderBase
|
||||
HostBase = base.HostBase
|
||||
ServiceBase = base.ServiceBase
|
||||
|
||||
@@ -22,8 +22,8 @@ import sys
|
||||
from oslo.config import cfg
|
||||
|
||||
_LIMITS_OPTIONS = [
|
||||
cfg.IntOpt('default_hostname_paging', default=10,
|
||||
help='Default hostname pagination size')
|
||||
cfg.IntOpt('default_services_paging', default=10,
|
||||
help='Default services pagination size')
|
||||
]
|
||||
|
||||
_LIMITS_GROUP = 'limits:storage'
|
||||
@@ -66,15 +66,14 @@ class CDNProviderBase(ProviderBase):
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractproperty
|
||||
def host_controller(self):
|
||||
def service_controller(self):
|
||||
"""Returns the extension's hostname controller."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class HostBase(object):
|
||||
"""This class is responsible for managing hostnames.
|
||||
Hostname operations include CRUD, etc.
|
||||
class ServiceBase(object):
|
||||
"""This class is responsible for managing services.
|
||||
"""
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
|
||||
@@ -22,6 +22,6 @@ Field Mappings:
|
||||
updated and documented in each controller class.
|
||||
"""
|
||||
|
||||
from cdn.provider.fastly import hosts
|
||||
from cdn.provider.fastly import services
|
||||
|
||||
HostController = hosts.HostController
|
||||
ServiceController = services.ServiceController
|
||||
|
||||
@@ -52,5 +52,5 @@ class CDNProvider(provider.CDNProviderBase):
|
||||
return self.client
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def host_controller(self):
|
||||
return controllers.HostController(self)
|
||||
def service_controller(self):
|
||||
return controllers.ServiceController(self)
|
||||
|
||||
@@ -19,10 +19,10 @@ import json
|
||||
from cdn.provider import base
|
||||
|
||||
|
||||
class HostController(base.HostBase):
|
||||
class ServiceController(base.ServiceBase):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(HostController, self).__init__()
|
||||
super(ServiceController, self).__init__()
|
||||
|
||||
self.client = driver.client
|
||||
self.current_customer = self.client.get_current_customer()
|
||||
@@ -22,6 +22,6 @@ Field Mappings:
|
||||
updated and documented in each controller class.
|
||||
"""
|
||||
|
||||
from cdn.provider.sample import hosts
|
||||
from cdn.provider.sample import services
|
||||
|
||||
HostController = hosts.HostController
|
||||
ServiceController = services.ServiceController
|
||||
|
||||
@@ -34,5 +34,5 @@ class CDNProvider(provider.CDNProviderBase):
|
||||
return True
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def host_controller(self):
|
||||
return controllers.HostController()
|
||||
def service_controller(self):
|
||||
return controllers.ServiceController()
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
from cdn.provider import base
|
||||
|
||||
|
||||
class HostController(base.HostBase):
|
||||
class ServiceController(base.ServiceBase):
|
||||
|
||||
def __init__(self):
|
||||
super(HostController, self).__init__()
|
||||
super(ServiceController, self).__init__()
|
||||
|
||||
self.provider_resp = base.ProviderResponse("sample")
|
||||
|
||||
@@ -4,5 +4,4 @@ from cdn.storage import base
|
||||
|
||||
# Hoist classes into package namespace
|
||||
StorageDriverBase = base.StorageDriverBase
|
||||
|
||||
HostBase = base.HostBase
|
||||
ServicesBase = base.ServicesBase
|
||||
|
||||
@@ -19,8 +19,8 @@ import six
|
||||
from oslo.config import cfg
|
||||
|
||||
_LIMITS_OPTIONS = [
|
||||
cfg.IntOpt('default_hostname_paging', default=10,
|
||||
help='Default hostname pagination size')
|
||||
cfg.IntOpt('default_services_paging', default=10,
|
||||
help='Default services pagination size')
|
||||
]
|
||||
|
||||
_LIMITS_GROUP = 'limits:storage'
|
||||
@@ -67,7 +67,7 @@ class StorageDriverBase(DriverBase):
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractproperty
|
||||
def host_controller(self):
|
||||
def service_controller(self):
|
||||
"""Returns the driver's hostname controller."""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -84,14 +84,13 @@ class ControllerBase(object):
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class HostBase(ControllerBase):
|
||||
"""This class is responsible for managing hostnames.
|
||||
Hostname operations include CRUD, etc.
|
||||
class ServicesBase(ControllerBase):
|
||||
"""This class is responsible for managing Services
|
||||
"""
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
def __init__(self, driver):
|
||||
super(HostBase, self).__init__(driver)
|
||||
super(ServicesBase, self).__init__(driver)
|
||||
|
||||
self.wrapper = ProviderWrapper()
|
||||
|
||||
@@ -119,12 +118,12 @@ class HostBase(ControllerBase):
|
||||
class ProviderWrapper(object):
|
||||
|
||||
def create(self, ext, service_name, service_json):
|
||||
return ext.obj.host_controller.create(service_name, service_json)
|
||||
return ext.obj.service_controller.create(service_name, service_json)
|
||||
|
||||
def update(self, ext, service_name):
|
||||
return ext.obj.host_controller.update(service_name)
|
||||
return ext.obj.service_controller.update(service_name)
|
||||
|
||||
def delete(self, ext, service_name):
|
||||
return ext.obj.host_controller.delete(service_name)
|
||||
return ext.obj.service_controller.delete(service_name)
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,6 @@ Field Mappings:
|
||||
updated and documented in each controller class.
|
||||
"""
|
||||
|
||||
from cdn.storage.cassandra import hosts
|
||||
from cdn.storage.cassandra import services
|
||||
|
||||
HostController = hosts.HostController
|
||||
ServicesController = services.ServicesController
|
||||
|
||||
@@ -61,9 +61,9 @@ class StorageDriver(storage.StorageDriverBase):
|
||||
return _connection(self.cassandra_conf)
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def host_controller(self):
|
||||
return controllers.HostController(self)
|
||||
def service_controller(self):
|
||||
return controllers.ServicesController(self)
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def host_database(self):
|
||||
def service_database(self):
|
||||
return self.connection
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
# Copyright (c) 2014 Rackspace, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import uuid
|
||||
|
||||
from cdn.storage import base
|
||||
|
||||
CQL_CREATE_SERVICE = '''
|
||||
INSERT INTO services (servicename, serviceid)
|
||||
VALUES (%s, %s)
|
||||
'''
|
||||
|
||||
class HostController(base.HostBase):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HostController, self).__init__(*args, **kwargs)
|
||||
|
||||
self._session = self.driver.host_database
|
||||
|
||||
|
||||
def list(self):
|
||||
hostnames = [
|
||||
{
|
||||
'hostname': 'www.mywebsite.com',
|
||||
'description': 'My Sample Website using Cassandra'
|
||||
},
|
||||
{
|
||||
'hostname': 'www.myotherwebsite.com',
|
||||
'description': 'My Other Website'
|
||||
}
|
||||
]
|
||||
|
||||
return hostnames
|
||||
|
||||
def get(self):
|
||||
# get the requested hostname from storage
|
||||
print "get hostname"
|
||||
|
||||
def create(self, service_name, service_json):
|
||||
|
||||
# create the hostname in storage
|
||||
service = service_json
|
||||
|
||||
"""Creates a new service"""
|
||||
args = (service_name, uuid.uuid1())
|
||||
res = self._session.execute(CQL_CREATE_SERVICE, args)
|
||||
|
||||
print "stored new record in cassandra"
|
||||
|
||||
|
||||
# create at providers
|
||||
providers = super(HostController, self).create(service_name, service)
|
||||
|
||||
return providers
|
||||
|
||||
def update(self, service_name, service_json):
|
||||
# update configuration in storage
|
||||
|
||||
# update at providers
|
||||
return super(HostController, self).update(service_name, service_json)
|
||||
|
||||
def delete(self, service_name):
|
||||
# delete local configuration from storage
|
||||
|
||||
# delete from providers
|
||||
return super(HostController, self).delete(service_name)
|
||||
|
||||
|
||||
123
cdn/storage/cassandra/services.py
Normal file
123
cdn/storage/cassandra/services.py
Normal file
@@ -0,0 +1,123 @@
|
||||
# Copyright (c) 2014 Rackspace, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import uuid
|
||||
|
||||
from cdn.storage import base
|
||||
|
||||
CQL_CREATE_SERVICE = '''
|
||||
INSERT INTO services (servicename, serviceid)
|
||||
VALUES (%s, %s)
|
||||
'''
|
||||
|
||||
class ServicesController(base.ServicesBase):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ServicesController, self).__init__(*args, **kwargs)
|
||||
|
||||
self._session = self.driver.service_database
|
||||
|
||||
|
||||
def list(self):
|
||||
services = {
|
||||
"links": [
|
||||
{
|
||||
"rel": "next",
|
||||
"href": "/v1.0/services?marker=www.myothersite.com&limit=20"
|
||||
}
|
||||
],
|
||||
"services" : [
|
||||
{
|
||||
"domains": [
|
||||
{
|
||||
"domain": "www.mywebsite.com"
|
||||
}
|
||||
],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "mywebsite.com",
|
||||
"port": 80,
|
||||
"ssl": False
|
||||
}
|
||||
],
|
||||
"caching": [
|
||||
{ "name" : "default", "ttl" : 3600 },
|
||||
{
|
||||
"name" : "home",
|
||||
"ttl" : 17200,
|
||||
"rules" : [
|
||||
{ "name" : "index", "request_url" : "/index.htm" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "images",
|
||||
"ttl" : 12800,
|
||||
"rules" : [
|
||||
{ "name" : "images", "request_url" : "*.png" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"restrictions" : [
|
||||
{
|
||||
"name" : "website only",
|
||||
"rules" : [ { "name" : "mywebsite.com", "http_host" : "www.mywebsite.com" } ]
|
||||
}
|
||||
],
|
||||
"links" : [
|
||||
{
|
||||
"href": "/v1.0/services/mywebsite",
|
||||
"rel" : "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return services
|
||||
|
||||
def get(self):
|
||||
# get the requested service from storage
|
||||
print "get service"
|
||||
|
||||
def create(self, service_name, service_json):
|
||||
|
||||
# create the service in storage
|
||||
service = service_json
|
||||
|
||||
"""Creates a new service"""
|
||||
args = (service_name, uuid.uuid1())
|
||||
res = self._session.execute(CQL_CREATE_SERVICE, args)
|
||||
|
||||
print "stored new record in cassandra"
|
||||
|
||||
|
||||
# create at providers
|
||||
providers = super(ServicesController, self).create(service_name, service)
|
||||
|
||||
return providers
|
||||
|
||||
def update(self, service_name, service_json):
|
||||
# update configuration in storage
|
||||
|
||||
# update at providers
|
||||
return super(ServicesController, self).update(service_name, service_json)
|
||||
|
||||
def delete(self, service_name):
|
||||
# delete local configuration from storage
|
||||
|
||||
# delete from providers
|
||||
return super(ServicesController, self).delete(service_name)
|
||||
|
||||
|
||||
@@ -24,4 +24,4 @@ Field Mappings:
|
||||
|
||||
from cdn.storage.mongodb import hosts
|
||||
|
||||
HostController = hosts.HostController
|
||||
ServicesController = servicess.ServicesController
|
||||
|
||||
@@ -79,21 +79,23 @@ class StorageDriver(storage.StorageDriverBase):
|
||||
except pymongo.errors.PyMongoError:
|
||||
return False
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def host_database(self):
|
||||
"""Database dedicated to the "host" collection.
|
||||
|
||||
The host collection is separated out into its own database.
|
||||
"""
|
||||
|
||||
name = self.mongodb_conf.database + '_host'
|
||||
return self.connection[name]
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def connection(self):
|
||||
"""MongoDB client connection instance."""
|
||||
return _connection(self.mongodb_conf)
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def host_controller(self):
|
||||
return controllers.HostController(self.providers)
|
||||
def service_controller(self):
|
||||
return controllers.ServicesController(self.providers)
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def service_database(self):
|
||||
"""Database dedicated to the "services" collection.
|
||||
|
||||
The services collection is separated out into its own database.
|
||||
"""
|
||||
|
||||
name = self.mongodb_conf.database + '_services'
|
||||
return self.connection[name]
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
# Copyright (c) 2014 Rackspace, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# stevedore/example/simple.py
|
||||
from cdn.storage import base
|
||||
|
||||
|
||||
class HostController(base.HostBase):
|
||||
|
||||
def list(self):
|
||||
hostnames = [
|
||||
{
|
||||
'hostname': 'www.mywebsite.com',
|
||||
'description': 'My Sample Website using Mongo'
|
||||
},
|
||||
{
|
||||
'hostname': 'www.myotherwebsite.com',
|
||||
'description': 'My Other Website'
|
||||
}
|
||||
]
|
||||
|
||||
return hostnames
|
||||
|
||||
def get(self):
|
||||
# get the requested hostname from storage
|
||||
print "get hostname"
|
||||
|
||||
def create(self, service_name, service_json):
|
||||
|
||||
# create the hostname in storage
|
||||
service = service_json
|
||||
|
||||
# create at providers
|
||||
return super(HostController, self).create(service_name, service)
|
||||
|
||||
def update(self, service_name, service_json):
|
||||
# update configuration in storage
|
||||
|
||||
# update at providers
|
||||
return super(HostController, self).update(service_name, service_json)
|
||||
|
||||
def delete(self, service_name):
|
||||
# delete local configuration from storage
|
||||
|
||||
# delete from providers
|
||||
return super(HostController, self).delete(service_name)
|
||||
|
||||
|
||||
103
cdn/storage/mongodb/services.py
Normal file
103
cdn/storage/mongodb/services.py
Normal file
@@ -0,0 +1,103 @@
|
||||
# Copyright (c) 2014 Rackspace, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# stevedore/example/simple.py
|
||||
from cdn.storage import base
|
||||
|
||||
|
||||
class ServicesController(base.ServicesBase):
|
||||
|
||||
def list(self):
|
||||
services = {
|
||||
"links": [
|
||||
{
|
||||
"rel": "next",
|
||||
"href": "/v1.0/services?marker=www.myothersite.com&limit=20"
|
||||
}
|
||||
],
|
||||
"services" : [
|
||||
{
|
||||
"domains": [
|
||||
{
|
||||
"domain": "www.mywebsite.com"
|
||||
}
|
||||
],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "mywebsite.com",
|
||||
"port": 80,
|
||||
"ssl": False
|
||||
}
|
||||
],
|
||||
"caching": [
|
||||
{ "name" : "default", "ttl" : 3600 },
|
||||
{
|
||||
"name" : "home",
|
||||
"ttl" : 17200,
|
||||
"rules" : [
|
||||
{ "name" : "index", "request_url" : "/index.htm" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "images",
|
||||
"ttl" : 12800,
|
||||
"rules" : [
|
||||
{ "name" : "images", "request_url" : "*.png" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"restrictions" : [
|
||||
{
|
||||
"name" : "website only",
|
||||
"rules" : [ { "name" : "mywebsite.com", "http_host" : "www.mywebsite.com" } ]
|
||||
}
|
||||
],
|
||||
"links" : [
|
||||
{
|
||||
"href": "/v1.0/services/mywebsite",
|
||||
"rel" : "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return services
|
||||
|
||||
def get(self):
|
||||
# get the requested service from storage
|
||||
print "get service"
|
||||
|
||||
def create(self, service_name, service_json):
|
||||
|
||||
# create the service in storage
|
||||
service = service_json
|
||||
|
||||
# create at providers
|
||||
return super(ServicesController, self).create(service_name, service)
|
||||
|
||||
def update(self, service_name, service_json):
|
||||
# update configuration in storage
|
||||
|
||||
# update at providers
|
||||
return super(ServicesController, self).update(service_name, service_json)
|
||||
|
||||
def delete(self, service_name):
|
||||
# delete local configuration from storage
|
||||
|
||||
# delete from providers
|
||||
return super(ServicesController, self).delete(service_name)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import six
|
||||
import cdn.openstack.common.log as logging
|
||||
from cdn import transport
|
||||
from cdn.transport.falcon import (
|
||||
v1, hosts
|
||||
v1, services
|
||||
)
|
||||
|
||||
|
||||
@@ -59,17 +59,17 @@ class TransportDriver(transport.DriverBase):
|
||||
version_path = "/v1.0"
|
||||
|
||||
# init the controllers
|
||||
host_controller = self._storage.host_controller
|
||||
service_controller = self._storage.service_controller
|
||||
|
||||
# setup the routes
|
||||
self.app.add_route(version_path,
|
||||
v1.V1Resource())
|
||||
|
||||
self.app.add_route(version_path + '/hosts',
|
||||
hosts.HostsResource(host_controller))
|
||||
self.app.add_route(version_path + '/services',
|
||||
services.ServicesResource(service_controller))
|
||||
|
||||
self.app.add_route(version_path + '/hosts/{service_name}',
|
||||
hosts.HostResource(host_controller))
|
||||
self.app.add_route(version_path + '/services/{service_name}',
|
||||
services.ServiceResource(service_controller))
|
||||
|
||||
def listen(self):
|
||||
"""Self-host using 'bind' and 'port' from the WSGI config group."""
|
||||
|
||||
@@ -17,48 +17,48 @@ import falcon
|
||||
import json
|
||||
|
||||
|
||||
class HostsResource:
|
||||
def __init__(self, host_controller):
|
||||
self.host_controller = host_controller
|
||||
class ServicesResource:
|
||||
def __init__(self, services_controller):
|
||||
self.services_controller = services_controller
|
||||
|
||||
def on_get(self, req, resp):
|
||||
"""Handles GET requests
|
||||
"""
|
||||
hostnames = self.host_controller.list()
|
||||
services = self.services_controller.list()
|
||||
resp.status = falcon.HTTP_200
|
||||
resp.body = json.dumps(hostnames)
|
||||
resp.body = json.dumps(services)
|
||||
|
||||
|
||||
class HostResource:
|
||||
def __init__(self, host_controller):
|
||||
self.host_controller = host_controller
|
||||
class ServiceResource:
|
||||
def __init__(self, service_controller):
|
||||
self.service_controller = service_controller
|
||||
|
||||
def on_get(self, req, resp, service_name):
|
||||
"""Handles GET requests
|
||||
"""
|
||||
host_response = self.host_controller.find(service_name)
|
||||
service = self.service_controller.find(service_name)
|
||||
resp.status = falcon.HTTP_200
|
||||
resp.body = json.dumps(host_response)
|
||||
resp.body = json.dumps(service)
|
||||
|
||||
def on_put(self, req, resp, service_name):
|
||||
"""Handles PUT requests
|
||||
"""
|
||||
service_json = json.loads(req.stream.read(req.content_length))
|
||||
|
||||
host_response = self.host_controller.create(service_name, service_json)
|
||||
service = self.service_controller.create(service_name, service_json)
|
||||
resp.status = falcon.HTTP_200
|
||||
resp.body = json.dumps(host_response)
|
||||
resp.body = json.dumps(service)
|
||||
|
||||
def on_patch(self, req, resp, service_name):
|
||||
"""Handles PATCH requests
|
||||
"""
|
||||
host_response = self.host_controller.update(service_name)
|
||||
service = self.service_controller.update(service_name)
|
||||
resp.status = falcon.HTTP_200
|
||||
resp.body = json.dumps(host_response)
|
||||
resp.body = json.dumps(service)
|
||||
|
||||
def on_delete(self, req, resp, service_name):
|
||||
"""Handles DELETE requests
|
||||
"""
|
||||
host_response = self.host_controller.delete(service_name)
|
||||
service = self.service_controller.delete(service_name)
|
||||
resp.status = falcon.HTTP_204
|
||||
resp.body = json.dumps(host_response)
|
||||
resp.body = json.dumps(service)
|
||||
Reference in New Issue
Block a user