Get Service (get one endpoint)

Change-Id: Ibd900a171239747169c99526c411f8a9ce7a20e7
This commit is contained in:
tonytan4ever 2014-09-18 16:20:04 -04:00
parent 7af26b4c95
commit 2bb62722f1
14 changed files with 245 additions and 159 deletions

View File

@ -24,6 +24,7 @@ class ProviderDetail(object):
def __init__(self, provider_service_id=None, access_urls=[],
status=u"unknown", name=None, error_info=None):
self._provider_service_id = provider_service_id
self._id = provider_service_id
self._access_urls = access_urls
self._status = status
self._name = name

View File

@ -35,6 +35,7 @@ class Service(common.DictSerializableModel):
self._caching = caching
self._restrictions = restrictions
self._status = u'unknown'
self._provider_details = {}
@property
def name(self):
@ -101,6 +102,14 @@ class Service(common.DictSerializableModel):
VALID_STATUSES)
)
@property
def provider_details(self):
return self._provider_details
@provider_details.setter
def provider_details(self, value):
self._provider_details = value
@classmethod
def init_from_dict(cls, input_dict):
"""Construct a model instance from a dictionary.

View File

@ -39,7 +39,8 @@ CQL_GET_SERVICE = '''
domains,
origins,
caching_rules,
restrictions
restrictions,
provider_details
FROM services
WHERE project_id = %(project_id)s AND service_name = %(service_name)s
'''
@ -130,8 +131,8 @@ class ServicesController(base.ServicesController):
origins = r.get("origins", [])
domains = r.get("domains", [])
origins = [origin.Origin(json.loads(o)['origin'],
json.loads(o).get("port", 80),
json.loads(o).get("ssl", False))
json.loads(o).get('port', 80),
json.loads(o).get('ssl', False))
for o in origins]
domains = [domain.Domain(json.loads(d)['domain']) for d in domains]
flavorRef = r.get("flavor_id")
@ -147,22 +148,37 @@ class ServicesController(base.ServicesController):
results = self.session.execute(CQL_GET_SERVICE, args)
if len(results) != 1:
raise LookupError("No service or multiple service found: %s"
% service_name)
raise ValueError('No service or multiple service found: %s'
% service_name)
services = []
for r in results:
name = r.get("service_name")
origins = r.get("origins", [])
domains = r.get("domains", [])
origins = [origin.Origin(json.loads(o)['origin'],
json.loads(o).get("port", 80),
json.loads(o).get("ssl", False))
for o in origins]
domains = [domain.Domain(json.loads(d)['domain']) for d in domains]
flavorRef = r.get("flavor_id")
services.append(service.Service(name, domains, origins, flavorRef))
return services[0]
# at this point, it is certain that there's exactly 1 result in
# results.
result = results[0]
name = result.get('service_name')
origins = result.get('origins', [])
domains = result.get('domains', [])
origins = [origin.Origin(json.loads(o)['origin'],
json.loads(o).get('port', 80),
json.loads(o).get('ssl', False))
for o in origins]
domains = [domain.Domain(json.loads(d)['domain']) for d in domains]
flavorRef = result.get("flavor_id")
s = service.Service(name, domains, origins, flavorRef)
provider_detail_results = result.get('provider_details')
provider_details_dict = {}
for provider_name in provider_detail_results:
provider_detail_dict = json.loads(
provider_detail_results[provider_name])
provider_service_id = provider_detail_dict.get('id', None)
access_urls = provider_detail_dict.get('access_urls', [])
status = provider_detail_dict.get('status', u'unknown')
provider_detail_obj = provider_details.ProviderDetail(
provider_service_id=provider_service_id,
access_urls=access_urls,
status=status)
provider_details_dict[provider_name] = provider_detail_obj
s.provider_details = provider_details_dict
return s
def create(self, project_id, service_obj):
# create the service in storage
@ -172,7 +188,7 @@ class ServicesController(base.ServicesController):
# Note: If it does, no LookupError will be raised
try:
self.get(project_id, service_name)
except LookupError:
except ValueError: # this value error means this service doesn't exist
pass
else:
raise ValueError("Service %s already exists..." % service_name)
@ -232,12 +248,13 @@ class ServicesController(base.ServicesController):
results = {}
for provider_name in exec_results[0]:
provider_detail_dict = json.loads(exec_results[0][provider_name])
pr_id = provider_detail_dict.get("provider_service_id", None)
provider_service_id = provider_detail_dict.get('id', None)
access_urls = provider_detail_dict.get("access_urls", None)
status = provider_detail_dict.get("status", u'unknown')
error_info = provider_detail_dict.get("error_info", None)
provider_detail_obj = provider_details.ProviderDetail(
provider_service_id=pr_id,
provider_service_id=provider_service_id,
access_urls=access_urls,
status=status,
error_info=error_info)

View File

@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from poppy.model.helpers import domain
from poppy.model.helpers import origin
from poppy.model.helpers import provider_details
@ -27,122 +29,139 @@ class ServicesController(base.ServicesController):
return self._driver.database
def list(self, project_id, marker=None, limit=None):
services = [
{
"name": "mockdb1_service_name",
"domains": [
{
"domain": "www.mywebsite.com"
}
],
"origins": [
{
"origin": "mywebsite.com",
"port": 80,
"ssl": False
}
],
"flavorRef": "standard",
"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"
}
]
}
],
}
]
services = [{'name': 'mockdb1_service_name',
'domains': [{'domain': 'www.mywebsite.com'}],
'origins': [{'origin': 'mywebsite.com',
'port': 80,
'ssl': False}],
'flavorRef': 'standard',
'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'}]}],
'provider_details':
{
'MaxCDN':
'{\"id\": 11942,'
' \"access_urls\": '
'[\"mypullzone.netdata.com\"]}',
'Mock':
'{\"id\": 73242,'
' \"access_urls\": [\"mycdn.mock.com\"]}',
'CloudFront':
'{\"id\": \"5ABC892\",'
' \"access_urls\": '
'[\"cf123.cloudcf.com\"]}',
'Fastly':
'{\"id\": 3488,'
' \"access_urls\": '
'[\"mockcf123.fastly.prod.com\"]}'
}}
]
services_result = []
for r in services:
name = r.get("name")
origins = r.get("origins", [])
domains = r.get("domains", [])
name = r.get('name', 'unnamed')
origins = r.get('origins', [])
domains = r.get('domains', [])
flavorRef = r.get('flavorRef')
provider_detail_dicts = r.get('provider_details')
origins = [origin.Origin(d) for d in origins]
domains = [domain.Domain(d) for d in domains]
flavorRef = r.get("name").split("/")[-1]
services_result.append(service.Service(name, domains, origins,
flavorRef))
provider_details_dict = {}
for provider_name in provider_detail_dicts:
provider_detail_dict = json.loads(
provider_detail_dicts[provider_name])
provider_service_id = provider_detail_dict.get('id', None)
access_urls = provider_detail_dict.get('access_urls', [])
status = provider_detail_dict.get('status', u'unknown')
provider_detail_obj = provider_details.ProviderDetail(
provider_service_id=provider_service_id,
access_urls=access_urls,
status=status)
provider_details_dict[provider_name] = provider_detail_obj
service_result = service.Service(name, domains, origins, flavorRef)
service_result.provider_details = provider_details_dict
services_result.append(service_result)
return services_result
def get(self, project_id, service_name):
# get the requested service from storage
service_dict = {
"name": service_name,
"domains": [
{
"domain": "www.mywebsite.com"
}
],
"origins": [
{
"origin": "mywebsite.com",
"port": 80,
"ssl": False
}
],
"flavorRef": "standard",
"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"
}
]
}
],
}
if service_name == "non_exist_service_name":
raise ValueError("service: % does not exist")
service_dict = {'name': service_name,
'domains': [{'domain': 'www.mywebsite.com'}],
'origins': [{'origin': 'mywebsite.com',
'port': 80,
'ssl': False}],
'flavorRef': 'standard',
'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'}]}],
'provider_details':
{
'MaxCDN':
'{\"id\": 11942,'
' \"access_urls\": '
'[\"mypullzone.netdata.com\"]}',
'Mock':
'{\"id\": 73242,'
' \"access_urls\": '
'[\"mycdn.mock.com\"]}',
'CloudFront':
'{\"id\": \"5ABC892\",'
' \"access_urls\": '
'[\"cf123.cloudcf.com\"]}',
'Fastly':
'{\"id\": 3488,'
' \"access_urls\": '
'[\"mockcf123.fastly.prod.com\"'
']}'
}}
name = service_dict.get("name")
origins = service_dict.get("origins", [])
domains = service_dict.get("domains", [])
name = service_dict.get('name', 'unnamed')
origins = service_dict.get('origins', [])
domains = service_dict.get('domains', [])
origins = [origin.Origin(d) for d in origins]
domains = [domain.Domain(d) for d in domains]
flavorRef = service_dict.get("name").split("/")[-1]
flavorRef = service_dict.get('flavorRef')
provider_detail_dicts = service_dict.get('provider_details')
services_result = service.Service(name, domains, origins, flavorRef)
provider_details_dict = {}
for provider_name in provider_detail_dicts:
provider_detail_dict = json.loads(
provider_detail_dicts[provider_name])
provider_service_id = provider_detail_dict.get('id', None)
access_urls = provider_detail_dict.get('access_urls', [])
status = provider_detail_dict.get('status', u'unknown')
provider_detail_obj = provider_details.ProviderDetail(
provider_service_id=provider_service_id,
access_urls=access_urls,
status=status)
provider_details_dict[provider_name] = provider_detail_obj
services_result.provider_details = provider_details_dict
return services_result
def create(self, project_id, service_obj):
@ -152,12 +171,12 @@ class ServicesController(base.ServicesController):
def update(self, project_id, service_name, service_json):
# update configuration in storage
return ""
return ''
def delete(self, project_id, service_name):
# delete from providers
return ""
return ''
def get_provider_details(self, project_id, service_name):
return {

View File

@ -53,7 +53,12 @@ class ServicesController(base.Controller):
@pecan.expose('json')
def get_one(self, service_name):
services_controller = self._driver.manager.services_controller
service_obj = services_controller.get(self.project_id, service_name)
try:
service_obj = services_controller.get(
self.project_id, service_name)
except ValueError:
pecan.abort(404, detail='service %s is not found' %
service_name)
# convert a service model into a response service model
return resp_service_model.Model(service_obj)

View File

@ -18,6 +18,9 @@ try:
except ImportError: # pragma: no cover
import collections # pragma: no cover
import pecan
from poppy.common import uri
from poppy.transport.pecan.models.response import domain
from poppy.transport.pecan.models.response import link
from poppy.transport.pecan.models.response import origin
@ -29,7 +32,7 @@ class Model(collections.OrderedDict):
def __init__(self, service_obj):
super(Model, self).__init__()
self["name"] = service_obj.name,
self["name"] = service_obj.name
self["domains"] = [domain.Model(d) for d in service_obj.domains]
self["origins"] = [origin.Model(o) for o in service_obj.origins]
self["status"] = service_obj.status
@ -37,5 +40,15 @@ class Model(collections.OrderedDict):
# TODO(tonytan4ever) : add access_url links.
# This has things to do with provider_detail change. (CDN-172)
self["links"] = [link.Model(
'/v1.0/services/{0}'.format(self["name"]),
str(
uri.encode(u'{0}/v1.0/services/{1}'.format(
pecan.request.host_url,
self['name']))),
'self')]
for provider_name in service_obj.provider_details:
for access_url in (
service_obj.provider_details[provider_name].access_urls):
self["links"].append(link.Model(
access_url,
'access_url'))

View File

@ -47,15 +47,12 @@ class ServiceControllerTest(base.FunctionalTest):
self.assertTrue("domains" in response_dict)
self.assertTrue("origins" in response_dict)
def test_get_one_not_exist(self):
self.assertRaises(app.AppError, self.app.get,
'/v1.0/0001/services/non_exist_service_name')
@ddt.file_data("data_create_service.json")
def test_create(self, service_json):
# create with errorenous data: invalid json data
self.assertRaises(app.AppError, self.app.post,
'/v1.0/0001/services',
params="{", headers={
"Content-Type": "application/json"
})
# create with good data
response = self.app.post('/v1.0/0001/services',
params=json.dumps(service_json),
@ -64,6 +61,13 @@ class ServiceControllerTest(base.FunctionalTest):
@ddt.file_data("data_create_service_bad_input_json.json")
def test_create_with_bad_input_json(self, service_json):
# create with errorenous data: invalid json data
self.assertRaises(app.AppError, self.app.post,
'/v1.0/0001/services',
params="{", headers={
"Content-Type": "application/json"
})
# create with errorenous data
self.assertRaises(app.AppError, self.app.post,
'/v1.0/0001/services',

View File

@ -1,9 +1,9 @@
{
"provider_details":
{
"MaxCDN": "{\"id\": 11942, \"access_url\": \"mypullzone.netdata.com\"}",
"Mock": "{\"id\": 73242, \"access_url\": \"mycdn.mock.com\"}",
"CloudFront": "{\"id\": \"5ABC892\", \"access_url\": \"cf123.cloudcf.com\"}",
"Fastly": "{\"id\": 3488, \"access_url\": \"mockcf123.fastly.prod.com\"}"
"MaxCDN": "{\"id\": 11942, \"access_urls\": [\"mypullzone.netdata.com\"]}",
"Mock": "{\"id\": 73242, \"access_urls\": [\"mycdn.mock.com\"]}",
"CloudFront": "{\"id\": \"5ABC892\", \"access_urls\": [\"cf123.cloudcf.com\"]}",
"Fastly": "{\"id\": 3488, \"access_urls\": [\"mockcf123.fastly.prod.com\"]}"
}
}

View File

@ -32,7 +32,7 @@ class TestProviderWrapper(base.TestCase):
self.fake_provider_details = {
"Fastly": provider_details.ProviderDetail(
provider_service_id=uuid.uuid1(),
access_urls='mydummywebsite.prod.fastly.com')}
access_urls=['mydummywebsite.prod.fastly.com'])}
def test_update_with_keyerror(self):
mock_ext = mock.Mock(provider_name="no_existent_provider")

View File

@ -146,13 +146,12 @@ class DefaultManagerServiceTests(base.TestCase):
provider_detail_dict = json.loads(
provider_details_json[provider_name]
)
provider_service_id = provider_detail_dict.get(
"provider_service_id", None)
access_urls = provider_detail_dict.get("access_url", None)
status = provider_detail_dict.get("status", u'unknown')
provider_service_id = provider_detail_dict.get('id', None)
access_url = provider_detail_dict.get('access_url', None)
status = provider_detail_dict.get('status', u'unknown')
provider_detail_obj = provider_details.ProviderDetail(
provider_service_id=provider_service_id,
access_urls=access_urls,
access_urls=access_url,
status=status)
self.provider_details[provider_name] = provider_detail_obj
@ -181,10 +180,9 @@ class DefaultManagerServiceTests(base.TestCase):
provider_detail_dict = json.loads(
provider_details_json[provider_name]
)
provider_service_id = provider_detail_dict.get(
"provider_service_id", None)
access_urls = provider_detail_dict.get("access_urls", None)
status = provider_detail_dict.get("status", u'unknown')
provider_service_id = provider_detail_dict.get('id', None)
access_urls = provider_detail_dict.get('access_urls', [])
status = provider_detail_dict.get('status', u'unknown')
provider_detail_obj = provider_details.ProviderDetail(
provider_service_id=provider_service_id,
access_urls=access_urls,

View File

@ -15,7 +15,14 @@
"flavor_id" : "standard",
"restrictions": [
"{\"rules\": [{\"http_host\": \"www.mocksite.com\", \"name\": \"mocksite.com\"}], \"name\": \"website only\"}"
]
],
"provider_details":
{
"MaxCDN": "{\"id\": 11942, \"access_urls\": [\"mypullzone.netdata.com\"]}",
"Mock": "{\"id\": 73242, \"access_urls\": [\"mycdn.mock.com\"]}",
"CloudFront": "{\"id\": \"5ABC892\", \"access_urls\": [\"cf123.cloudcf.com\"]}",
"Fastly": "{\"id\": 3488, \"access_urls\": [\"mockcf123.fastly.prod.com\"]}"
}
}
]

View File

@ -15,7 +15,14 @@
],
"restrictions": [
"{\"rules\": [{\"http_host\": \"www.mocksite.com\", \"name\": \"mocksite.com\"}], \"name\": \"website only\"}"
]
],
"provider_details":
{
"MaxCDN": "{\"id\": 11942, \"access_urls\": [\"mypullzone.netdata.com\"]}",
"Mock": "{\"id\": 73242, \"access_urls\": [\"mycdn.mock.com\"]}",
"CloudFront": "{\"id\": \"5ABC892\", \"access_urls\": [\"cf123.cloudcf.com\"]}",
"Fastly": "{\"id\": 3488, \"access_urls\": [\"mockcf123.fastly.prod.com\"]}"
}
},
{
"service_name": "another_mocksite",
@ -32,7 +39,14 @@
],
"restrictions":[
"{\"rules\": [{\"http_host\": \"www.mocksite.co.uk\", \"name\": \"mocksite.co.uk\"}], \"name\": \"website only\"}"
]
],
"provider_details":
{
"MaxCDN": "{\"id\": 11942, \"access_urls\": [\"mypullzone.netdata.com\"]}",
"Mock": "{\"id\": 73242, \"access_urls\": [\"mycdn.mock.com\"]}",
"CloudFront": "{\"id\": \"5ABC892\", \"access_urls\": [\"cf123.cloudcf.com\"]}",
"Fastly": "{\"id\": 3488, \"access_urls\": [\"mockcf123.fastly.prod.com\"]}"
}
}
]
}

View File

@ -1,9 +1,9 @@
{
"provider_details":
{
"MaxCDN": "{\"provider_service_id\": 11942, \"access_urls\": [\"mypullzone.netdata.com\"]}",
"Mock": "{\"provider_service_id\": 73242, \"access_urls\": [\"mycdn.mock.com\"]}",
"CloudFront": "{\"provider_service_id\": \"5ABC892\", \"access_urls\": [\"cf123.cloudcf.com\"]}",
"Fastly": "{\"provider_service_id\": 3488, \"access_urls\": [\"mockcf123.fastly.prod.com\"]}"
"MaxCDN": "{\"id\": 11942, \"access_urls\": [\"mypullzone.netdata.com\"]}",
"Mock": "{\"id\": 73242, \"access_urls\": [\"mycdn.mock.com\"]}",
"CloudFront": "{\"id\": \"5ABC892\", \"access_urls\": [\"cf123.cloudcf.com\"]}",
"Fastly": "{\"id\": 3488, \"access_urls\": [\"mockcf123.fastly.prod.com\"]}"
}
}

View File

@ -65,14 +65,13 @@ class CassandraStorageServiceTests(base.TestCase):
# mock the response from cassandra
mock_execute.execute.return_value = []
self.assertRaises(LookupError, self.sc.get,
self.assertRaises(ValueError, self.sc.get,
self.project_id, self.service_name)
@ddt.file_data('../data/data_create_service.json')
@mock.patch.object(services.ServicesController, 'session')
@mock.patch.object(cassandra.cluster.Session, 'execute')
def test_create_service(self, value, mock_session, mock_execute):
value.update({'name': self.service_name})
service_obj = req_service.load_from_json(value)
responses = self.sc.create(self.project_id, service_obj)
@ -155,7 +154,7 @@ class CassandraStorageServiceTests(base.TestCase):
provider_detail_dict = json.loads(v)
provider_details_dict[k] = provider_details.ProviderDetail(
provider_service_id=(
provider_detail_dict["provider_service_id"]),
provider_detail_dict["id"]),
access_urls=provider_detail_dict["access_urls"])
# mock the response from cassandra