Merge "Support CAMP assembly resources"
This commit is contained in:
commit
cae69ca3ec
@ -14,7 +14,11 @@
|
||||
|
||||
import json
|
||||
|
||||
from tempest_lib import exceptions as tempest_exceptions
|
||||
import yaml
|
||||
|
||||
from functionaltests.api import base
|
||||
from functionaltests.api.camp.v1_1 import test_plans
|
||||
|
||||
|
||||
class TestAssembliesController(base.TestCase):
|
||||
@ -24,6 +28,21 @@ class TestAssembliesController(base.TestCase):
|
||||
self.client.delete_created_assemblies()
|
||||
self.client.delete_created_plans()
|
||||
|
||||
# TODO(gpilz) - this is a dup of a method in test_plans.TestPlansController
|
||||
def _create_camp_plan(self, data):
|
||||
yaml_data = yaml.dump(data)
|
||||
resp, body = self.client.post('camp/v1_1/plans', yaml_data,
|
||||
headers={'content-type':
|
||||
'application/x-yaml'})
|
||||
plan_resp = base.SolumResponse(resp=resp,
|
||||
body=body,
|
||||
body_type='json')
|
||||
uuid = plan_resp.uuid
|
||||
if uuid is not None:
|
||||
# share the Solum client's list of created plans
|
||||
self.client.created_plans.append(uuid)
|
||||
return plan_resp
|
||||
|
||||
def test_get_solum_assembly(self):
|
||||
"""Test the CAMP assemblies collection resource.
|
||||
|
||||
@ -38,24 +57,102 @@ class TestAssembliesController(base.TestCase):
|
||||
self.assertEqual(201, p_resp.status)
|
||||
a_resp = self.client.create_assembly(plan_uuid=p_resp.uuid)
|
||||
self.assertEqual(201, a_resp.status)
|
||||
new_uuid = a_resp.uuid
|
||||
|
||||
# get the CAMP assemblies resource
|
||||
# try to get to the newly created assembly through the CAMP assemblies
|
||||
# resource. it would be more efficient to simply take the UUID of the
|
||||
# newly created resource and create a CAMP API URI
|
||||
# (../camp/v1_1/assemblies/<uuid>) from that, but we want to test that
|
||||
# a link to the Solum-created assembly appears in in the list of links
|
||||
# in the CAMP plans resource.
|
||||
resp, body = self.client.get('camp/v1_1/assemblies')
|
||||
self.assertEqual(200, resp.status, 'GET assemblies resource')
|
||||
|
||||
# pick out the assemebly link for our new assembly uuid
|
||||
assemblies_dct = json.loads(body)
|
||||
assem_links = assemblies_dct['assembly_links']
|
||||
self.assertEqual(1, len(assem_links))
|
||||
camp_link = None
|
||||
for link in assemblies_dct['assembly_links']:
|
||||
link_uuid = link['href'].split("/")[-1]
|
||||
if link_uuid == new_uuid:
|
||||
camp_link = link
|
||||
|
||||
a_link = assem_links[0]
|
||||
msg = 'Unable to find link to newly created plan in CAMP plans'
|
||||
self.assertIsNotNone(camp_link, msg)
|
||||
|
||||
url = a_link['href'][len(self.client.base_url) + 1:]
|
||||
url = camp_link['href'][len(self.client.base_url) + 1:]
|
||||
msg = ("GET Solum assembly resource for %s" %
|
||||
a_link['target_name'])
|
||||
camp_link['target_name'])
|
||||
resp, body = self.client.get(url)
|
||||
self.assertEqual(200, resp.status, msg)
|
||||
|
||||
# right now, this looks like a Solum assembly, not a CAMP
|
||||
assembly = json.loads(body)
|
||||
self.assertEqual('assembly', assembly['type'])
|
||||
self.assertEqual(base.assembly_sample_data['name'], assembly['name'])
|
||||
|
||||
def test_create_camp_assembly(self):
|
||||
"""Test creating a CAMP assembly from a local plan resource.
|
||||
|
||||
Creates a plan resource then uses that to create an assembly resource.
|
||||
|
||||
"""
|
||||
if base.config_set_as('camp_enabled', False):
|
||||
self.skipTest('CAMP not enabled.')
|
||||
|
||||
# create a plan using the CAMP API
|
||||
resp = self._create_camp_plan(data=test_plans.sample_data)
|
||||
self.assertEqual(resp.status, 201)
|
||||
uri = (resp.data['uri']
|
||||
[len(self.client.base_url):])
|
||||
|
||||
ref_obj = json.dumps({'plan_uri': uri})
|
||||
|
||||
resp, body = self.client.post(
|
||||
'camp/v1_1/assemblies',
|
||||
ref_obj,
|
||||
headers={'content-type': 'application/json'})
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
assem_resp = base.SolumResponse(resp=resp,
|
||||
body=body,
|
||||
body_type='json')
|
||||
uuid = assem_resp.uuid
|
||||
if uuid is not None:
|
||||
# share the Solum client's list of created assemblies
|
||||
self.client.created_assemblies.append(uuid)
|
||||
|
||||
def test_delete_plan_with_assemblies(self):
|
||||
"""Test deleting a plan what has assemblies associated with it.
|
||||
|
||||
Creates a plan, an assembly, then tries to delete the plan.
|
||||
"""
|
||||
if base.config_set_as('camp_enabled', False):
|
||||
self.skipTest('CAMP not enabled.')
|
||||
|
||||
# create a plan using the CAMP API
|
||||
resp = self._create_camp_plan(data=test_plans.sample_data)
|
||||
self.assertEqual(resp.status, 201)
|
||||
plan_uri = (resp.data['uri']
|
||||
[len(self.client.base_url):])
|
||||
|
||||
ref_obj = json.dumps({'plan_uri': plan_uri})
|
||||
|
||||
resp, body = self.client.post(
|
||||
'camp/v1_1/assemblies',
|
||||
ref_obj,
|
||||
headers={'content-type': 'application/json'})
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
assem_resp = base.SolumResponse(resp=resp,
|
||||
body=body,
|
||||
body_type='json')
|
||||
uuid = assem_resp.uuid
|
||||
if uuid is not None:
|
||||
# share the Solum client's list of created assemblies
|
||||
self.client.created_assemblies.append(uuid)
|
||||
|
||||
# try to delete the plan before deleting the assembly
|
||||
# resp, body = self.client.delete(plan_uri[1:])
|
||||
# self.assertEqual(409, resp.status)
|
||||
|
||||
self.assertRaises(tempest_exceptions.Conflict,
|
||||
self.client.delete, plan_uri[1:])
|
||||
|
@ -90,11 +90,12 @@ class TestPlansController(base.TestCase):
|
||||
new_plan = p_resp.yaml_data
|
||||
new_uuid = new_plan['uuid']
|
||||
|
||||
# try to get to the newly created through the CAMP plans resource. it
|
||||
# would be more efficient to simply take the UUID of the newly created
|
||||
# resource and create a CAMP API URI (../camp/v1_1/plans/<uuid>) from
|
||||
# that, but we want to test that a link to the Solum-created plan
|
||||
# appears in in the list of links in the CAMP plans resource.
|
||||
# try to get to the newly plan created through the CAMP plans
|
||||
# resource. it would be more efficient to simply take the UUID of the
|
||||
# newly created resource and create a CAMP API URI
|
||||
# (../camp/v1_1/plans/<uuid>) from that, but we want to test that a
|
||||
# link to the Solum-created plan appears in in the list of links in
|
||||
# the CAMP plans resource.
|
||||
resp, body = self.client.get('camp/v1_1/plans')
|
||||
self.assertEqual(200, resp.status, 'GET plans resource')
|
||||
|
||||
|
@ -12,20 +12,34 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import urlparse
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from wsme.rest import json as wsme_json
|
||||
from wsme import types as wsme_types
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from solum.api.controllers.camp.v1_1.datamodel import assemblies as model
|
||||
from solum.api.controllers.camp.v1_1 import uris
|
||||
from solum.api.controllers import common_types
|
||||
from solum.api.handlers import assembly_handler
|
||||
from solum.api.handlers.camp import assembly_handler
|
||||
from solum.api.handlers.camp import plan_handler
|
||||
from solum.common import exception
|
||||
|
||||
|
||||
class AssembliesController(rest.RestController):
|
||||
"""CAMP v1.1 assemblies controller."""
|
||||
|
||||
@exception.wrap_wsme_controller_exception
|
||||
@wsme_pecan.wsexpose(None, wsme_types.text, status_code=204)
|
||||
def delete(self, uuid):
|
||||
"""Delete this assembly."""
|
||||
handler = assembly_handler.AssemblyHandler(
|
||||
pecan.request.security_context)
|
||||
handler.delete(uuid)
|
||||
|
||||
@exception.wrap_wsme_controller_exception
|
||||
@wsme_pecan.wsexpose(model.Assemblies)
|
||||
def get(self):
|
||||
@ -33,9 +47,9 @@ class AssembliesController(rest.RestController):
|
||||
pdef_uri = uris.DEPLOY_PARAMS_URI % pecan.request.host_url
|
||||
desc = "Solum CAMP API assemblies collection resource"
|
||||
|
||||
handlr = (assembly_handler.
|
||||
AssemblyHandler(pecan.request.security_context))
|
||||
asem_objs = handlr.get_all()
|
||||
handler = (assembly_handler.
|
||||
AssemblyHandler(pecan.request.security_context))
|
||||
asem_objs = handler.get_all()
|
||||
a_links = []
|
||||
for m in asem_objs:
|
||||
a_links.append(common_types.Link(href=uris.ASSEM_URI_STR %
|
||||
@ -59,3 +73,113 @@ class AssembliesController(rest.RestController):
|
||||
parameter_definitions_uri=pdef_uri)
|
||||
|
||||
return res
|
||||
|
||||
@exception.wrap_wsme_controller_exception
|
||||
@wsme_pecan.wsexpose(model.Assembly, wsme_types.text)
|
||||
def get_one(self, uuid):
|
||||
"""Return the appropriate CAMP-style assembly resource."""
|
||||
handler = assembly_handler.AssemblyHandler(
|
||||
pecan.request.security_context)
|
||||
return model.Assembly.from_db_model(handler.get(uuid),
|
||||
pecan.request.host_url)
|
||||
|
||||
@exception.wrap_pecan_controller_exception
|
||||
@pecan.expose('json', content_type='application/json')
|
||||
def post(self):
|
||||
"""Create a new application.
|
||||
|
||||
There are a number of ways to use this method to create a new
|
||||
application. See Section 6.11 of the CAMP v1.1 specification
|
||||
for an explanation of each. Use the Content-Type of request to
|
||||
determine what the client is trying to do.
|
||||
"""
|
||||
if pecan.request.content_type is None:
|
||||
raise exception.UnsupportedMediaType(
|
||||
name=pecan.request.content_type,
|
||||
method='POST')
|
||||
|
||||
req_content_type = pecan.request.content_type
|
||||
|
||||
# deploying by reference uses a JSON payload
|
||||
if req_content_type == 'application/json':
|
||||
payload = pecan.request.body
|
||||
if not payload or len(payload) < 1:
|
||||
raise exception.BadRequest(reason='empty request body')
|
||||
|
||||
try:
|
||||
json_ref_doc = json.loads(payload)
|
||||
except ValueError as excp:
|
||||
raise exception.BadRequest(reason='JSON object is invalid. '
|
||||
+ excp.message)
|
||||
|
||||
if 'plan_uri' in json_ref_doc:
|
||||
plan_uri_str = json_ref_doc['plan_uri']
|
||||
|
||||
# figure out if the plan uri is relative or absolute
|
||||
plan_uri = urlparse.urlparse(plan_uri_str)
|
||||
uri_path = plan_uri.path
|
||||
if not plan_uri.netloc:
|
||||
# should be something like "../plans/<uuid>" or
|
||||
# "/camp/v1_1/plans/<uuid> (include Solum plans)
|
||||
if (not uri_path.startswith('../plans/') and
|
||||
not uri_path.startswith('../../../v1/plans/') and
|
||||
not uri_path.startswith('/camp/v1_1/plans/') and
|
||||
not uri_path.startswith('/v1/plans/')):
|
||||
msg = 'plan_uri does not reference a plan resource'
|
||||
raise exception.BadRequest(reason=msg)
|
||||
|
||||
plan_uuid = plan_uri.path.split('/')[-1]
|
||||
|
||||
else:
|
||||
# We have an absolute URI. Try to figure out if it refers
|
||||
# to a plan on this Solum instance. Note the following code
|
||||
# does not support URI aliases. A request that contains
|
||||
# a 'plan_uri' with a network location that is different
|
||||
# than network location used to make this request but
|
||||
# which, nevertheless, still refers to this Solum instance
|
||||
# will experience a false negative. This code will treat
|
||||
# that plan as if it existed on another CAMP-compliant
|
||||
# server.
|
||||
if plan_uri_str.startswith(pecan.request.host_url):
|
||||
if (not uri_path.startswith('/camp/v1_1/plans/') and
|
||||
not uri_path.startswith('/v1/plans/')):
|
||||
msg = 'plan_uri does not reference a plan resource'
|
||||
raise exception.BadRequest(reason=msg)
|
||||
|
||||
plan_uuid = plan_uri.path.split('/')[-1]
|
||||
|
||||
else:
|
||||
# The plan exists on another server.
|
||||
# TODO(gpilz): support references to plans on other
|
||||
# servers
|
||||
raise exception.NotImplemented()
|
||||
|
||||
# resolve the local plan by its uuid. this will raise a
|
||||
# ResourceNotFound exception if there is no plan with
|
||||
# this uuid
|
||||
phandler = plan_handler.PlanHandler(
|
||||
pecan.request.security_context)
|
||||
plan_obj = phandler.get(plan_uuid)
|
||||
|
||||
elif 'pdp_uri' in json_ref_doc:
|
||||
# TODO(gpilz): support references to PDPs
|
||||
raise exception.NotImplemented()
|
||||
else:
|
||||
# must have either 'plan_uri' or 'pdp_uri'
|
||||
msg = 'JSON object must contain either plan_uri or pdp_uri'
|
||||
raise exception.BadRequest(reason=msg)
|
||||
else:
|
||||
# TODO(gpilz): support deploying an application by value
|
||||
raise exception.NotImplemented()
|
||||
|
||||
# at this point we expect to have a reference to a plan database object
|
||||
# for the plan that will be used to create the application
|
||||
ahandler = assembly_handler.AssemblyHandler(
|
||||
pecan.request.security_context)
|
||||
assem_db_obj = ahandler.create_from_plan(plan_obj)
|
||||
assem_model = model.Assembly.from_db_model(assem_db_obj,
|
||||
pecan.request.host_url)
|
||||
|
||||
pecan.response.status = 201
|
||||
pecan.response.location = assem_model.uri
|
||||
return wsme_json.tojson(model.Assembly, assem_model)
|
||||
|
@ -12,10 +12,47 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
|
||||
from wsme import types as wtypes
|
||||
|
||||
from solum.api.controllers.camp.v1_1 import uris
|
||||
from solum.api.controllers import common_types
|
||||
from solum.api.controllers.v1.datamodel import types as api_types
|
||||
|
||||
|
||||
class Assembly(api_types.Base):
|
||||
"""CAMP v1.1 assembly resource model."""
|
||||
|
||||
components = [common_types.Link]
|
||||
"""CAMP-defined, not currently used."""
|
||||
|
||||
plan_uri = common_types.Uri
|
||||
"""CAMP-defined, also used by Solum."""
|
||||
|
||||
operations_uri = common_types.Uri
|
||||
"""CAMP-defined, not currently used."""
|
||||
|
||||
sensors_uri = common_types.Uri
|
||||
"""CAMP-defined, not currently used."""
|
||||
|
||||
status = wtypes.text
|
||||
"""Solum extension."""
|
||||
|
||||
updated_at = datetime.datetime
|
||||
"""Solum extension."""
|
||||
|
||||
created_at = datetime.datetime
|
||||
"""Solum extension."""
|
||||
|
||||
@classmethod
|
||||
def from_db_model(cls, m, host_url):
|
||||
obj = super(Assembly, cls).from_db_model(m, host_url)
|
||||
obj.plan_uri = uris.PLAN_URI_STR % (host_url, m.plan_uuid)
|
||||
obj.uri = uris.ASSEM_URI_STR % (host_url, m.uuid)
|
||||
return obj
|
||||
|
||||
|
||||
class Assemblies(api_types.Base):
|
||||
"""CAMP v1.1 assemblies resource model."""
|
||||
|
||||
|
@ -27,7 +27,7 @@ import wsmeext.pecan as wsme_pecan
|
||||
from solum.api.controllers.camp.v1_1.datamodel import plans as model
|
||||
from solum.api.controllers.camp.v1_1 import uris
|
||||
from solum.api.controllers import common_types
|
||||
from solum.api.handlers import plan_handler as plan_handler
|
||||
from solum.api.handlers.camp import plan_handler as plan_handler
|
||||
from solum.common import exception
|
||||
from solum.common import yamlutils
|
||||
from solum.openstack.common.gettextutils import _
|
||||
@ -219,5 +219,8 @@ class PlansController(rest.RestController):
|
||||
|
||||
db_obj = handler.create(clean_plan(wjson.tojson(model.Plan,
|
||||
model_plan)))
|
||||
plan_dict = fluff_plan(db_obj.refined_content(), db_obj.uuid)
|
||||
|
||||
pecan.response.status = 201
|
||||
return fluff_plan(db_obj.refined_content(), db_obj.uuid)
|
||||
pecan.response.location = plan_dict['uri']
|
||||
return plan_dict
|
||||
|
@ -12,8 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# TODO(gilbert.pilz) - change this to point to CAMP-style assembly resource
|
||||
ASSEM_URI_STR = '%s/v1/assemblies/%s'
|
||||
ASSEM_URI_STR = '%s/camp/v1_1/assemblies/%s'
|
||||
|
||||
ASSEMS_URI_STR = '%s/camp/v1_1/assemblies'
|
||||
|
||||
|
50
solum/api/handlers/camp/assembly_handler.py
Normal file
50
solum/api/handlers/camp/assembly_handler.py
Normal file
@ -0,0 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# 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 solum.api.handlers import assembly_handler as solum_assem_handler
|
||||
from solum.common import solum_keystoneclient
|
||||
from solum import objects
|
||||
|
||||
|
||||
class AssemblyHandler(solum_assem_handler.AssemblyHandler):
|
||||
def create_from_plan(self, plan_obj):
|
||||
"""Create an application using a plan resource as a template."""
|
||||
db_obj = objects.registry.Assembly()
|
||||
db_obj.uuid = str(uuid.uuid4())
|
||||
db_obj.user_id = self.context.user
|
||||
db_obj.project_id = self.context.tenant
|
||||
db_obj.trigger_id = str(uuid.uuid4())
|
||||
db_obj.username = self.context.user_name
|
||||
|
||||
# create the trust_id and store it.
|
||||
ksc = solum_keystoneclient.KeystoneClientV3(self.context)
|
||||
trust_context = ksc.create_trust_context()
|
||||
db_obj.trust_id = trust_context.trust_id
|
||||
|
||||
# use the plan name as the name of this application
|
||||
db_obj.name = plan_obj.name + "_application"
|
||||
db_obj.plan_id = plan_obj.id
|
||||
db_obj.plan_uuid = plan_obj.uuid
|
||||
|
||||
db_obj.status = solum_assem_handler.ASSEMBLY_STATES.QUEUED
|
||||
db_obj.create(self.context)
|
||||
artifacts = plan_obj.raw_content.get('artifacts', [])
|
||||
|
||||
# build each artifact in the plan
|
||||
for arti in artifacts:
|
||||
self._build_artifact(assem=db_obj, artifact=arti)
|
||||
|
||||
return db_obj
|
27
solum/api/handlers/camp/plan_handler.py
Normal file
27
solum/api/handlers/camp/plan_handler.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# 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.
|
||||
|
||||
from solum.api.handlers import plan_handler as solum_plan_handler
|
||||
from solum import objects
|
||||
|
||||
|
||||
class PlanHandler(solum_plan_handler.PlanHandler):
|
||||
def delete(self, id):
|
||||
"""Override to simply delete the appropriate row in the DB.
|
||||
|
||||
This will raise an exception if any assemblies refer to this plan.
|
||||
"""
|
||||
db_obj = objects.registry.Plan.get_by_uuid(self.context, id)
|
||||
self._delete_params(db_obj.id)
|
||||
db_obj.destroy(self.context)
|
@ -12,6 +12,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
|
||||
import mock
|
||||
|
||||
from solum.api.controllers.camp.v1_1 import assemblies
|
||||
@ -22,22 +24,125 @@ from solum.tests import fakes
|
||||
|
||||
@mock.patch('pecan.request', new_callable=fakes.FakePecanRequest)
|
||||
@mock.patch('pecan.response', new_callable=fakes.FakePecanResponse)
|
||||
@mock.patch('solum.api.handlers.assembly_handler.AssemblyHandler')
|
||||
@mock.patch('solum.api.handlers.camp.assembly_handler.AssemblyHandler')
|
||||
@mock.patch('solum.api.handlers.camp.plan_handler.PlanHandler')
|
||||
class TestAssemblies(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestAssemblies, self).setUp()
|
||||
objects.load()
|
||||
|
||||
def test_assemblies_get(self, AssemblyHandler, resp_mock, request_mock):
|
||||
def test_assemblies_get(self, PlanHandler, AssemblyHandler, resp_mock,
|
||||
request_mock):
|
||||
hand_get_all = AssemblyHandler.return_value.get_all
|
||||
fake_assembly = fakes.FakeAssembly()
|
||||
hand_get_all.return_value = [fake_assembly]
|
||||
|
||||
cont = assemblies.AssembliesController()
|
||||
resp = cont.get()
|
||||
resp = assemblies.AssembliesController().get()
|
||||
self.assertIsNotNone(resp)
|
||||
self.assertEqual(200, resp_mock.status)
|
||||
self.assertIsNotNone(resp['result'].assembly_links)
|
||||
assembly_links = resp['result'].assembly_links
|
||||
self.assertEqual(1, len(assembly_links))
|
||||
self.assertEqual(fake_assembly.name, assembly_links[0].target_name)
|
||||
|
||||
def test_assemblies_post_no_content_type(self, PlanHandler,
|
||||
AssemblyHandler, resp_mock,
|
||||
request_mock):
|
||||
# creating an assembly requires a Content-Type so the CAMP impl
|
||||
# can figure out which mechanism the user wants
|
||||
request_mock.content_type = None
|
||||
|
||||
assemblies.AssembliesController().post()
|
||||
self.assertEqual(415, resp_mock.status)
|
||||
|
||||
def test_assemblies_post_ref_none(self, PlanHandler, AssemblyHandler,
|
||||
resp_mock, request_mock):
|
||||
# a Content-Type of 'application/json' indicates that the user is
|
||||
# providing a JSON object that references either a plan or a PDP
|
||||
request_mock.content_type = 'application/json'
|
||||
request_mock.body = None
|
||||
|
||||
assemblies.AssembliesController().post()
|
||||
self.assertEqual(400, resp_mock.status)
|
||||
|
||||
def test_assemblies_post_ref_empty_json(self, PlanHandler, AssemblyHandler,
|
||||
resp_mock, request_mock):
|
||||
# a Content-Type of 'application/json' indicates that the user is
|
||||
# providing a JSON object that references either a plan or a PDP
|
||||
request_mock.content_type = 'application/json'
|
||||
request_mock.body = '{}'
|
||||
|
||||
assemblies.AssembliesController().post()
|
||||
self.assertEqual(400, resp_mock.status)
|
||||
|
||||
def test_assemblies_post_ref_bad_rel_uri(self, PlanHandler,
|
||||
AssemblyHandler, resp_mock,
|
||||
request_mock):
|
||||
# a Content-Type of 'application/json' indicates that the user is
|
||||
# providing a JSON object that references either a plan or a PDP
|
||||
ref_object = {'plan_uri':
|
||||
'../fooble/24e3974c-195d-4a6a-96b0-7924ed3c742a'}
|
||||
request_mock.content_type = 'application/json'
|
||||
request_mock.body = json.dumps(ref_object)
|
||||
|
||||
assemblies.AssembliesController().post()
|
||||
self.assertEqual(400, resp_mock.status)
|
||||
|
||||
def test_assemblies_post_ref_rel_uris(self, PlanHandler, AssemblyHandler,
|
||||
resp_mock, request_mock):
|
||||
hand_get = PlanHandler.return_value.get
|
||||
hand_get.return_value = fakes.FakePlan()
|
||||
|
||||
hand_create_from_plan = AssemblyHandler.return_value.create_from_plan
|
||||
fake_assembly = fakes.FakeAssembly()
|
||||
hand_create_from_plan.return_value = fake_assembly
|
||||
|
||||
cntrl = assemblies.AssembliesController()
|
||||
|
||||
# test reference to CAMP plan relative to assemblies
|
||||
ref_object = {'plan_uri':
|
||||
'../plans/24e3974c-195d-4a6a-96b0-7924ed3c742a'}
|
||||
request_mock.content_type = 'application/json'
|
||||
request_mock.body = json.dumps(ref_object)
|
||||
|
||||
resp = cntrl.post()
|
||||
self.assertIsNotNone(resp)
|
||||
self.assertEqual(201, resp_mock.status)
|
||||
self.assertIsNotNone(resp_mock.location)
|
||||
self.assertEqual(fake_assembly.name, resp['name'])
|
||||
|
||||
# test reference to Solum plan relative to assemblies
|
||||
ref_object = {'plan_uri':
|
||||
'../../../v1/plans/24e3974c-195d-4a6a-96b0-7924ed3c742a'}
|
||||
request_mock.content_type = 'application/json'
|
||||
request_mock.body = json.dumps(ref_object)
|
||||
|
||||
resp = cntrl.post()
|
||||
self.assertIsNotNone(resp)
|
||||
self.assertEqual(201, resp_mock.status)
|
||||
self.assertIsNotNone(resp_mock.location)
|
||||
self.assertEqual(fake_assembly.name, resp['name'])
|
||||
|
||||
# test reference to CAMP plan relative to root
|
||||
ref_object = {'plan_uri':
|
||||
'/camp/v1_1/plans/24e3974c-195d-4a6a-96b0-7924ed3c742a'}
|
||||
request_mock.content_type = 'application/json'
|
||||
request_mock.body = json.dumps(ref_object)
|
||||
|
||||
resp = cntrl.post()
|
||||
self.assertIsNotNone(resp)
|
||||
self.assertEqual(201, resp_mock.status)
|
||||
self.assertIsNotNone(resp_mock.location)
|
||||
self.assertEqual(fake_assembly.name, resp['name'])
|
||||
|
||||
# test reference to Solum plan relative to root
|
||||
ref_object = {'plan_uri':
|
||||
'/v1/plans/24e3974c-195d-4a6a-96b0-7924ed3c742a'}
|
||||
request_mock.content_type = 'application/json'
|
||||
request_mock.body = json.dumps(ref_object)
|
||||
|
||||
resp = cntrl.post()
|
||||
self.assertIsNotNone(resp)
|
||||
self.assertEqual(201, resp_mock.status)
|
||||
self.assertIsNotNone(resp_mock.location)
|
||||
self.assertEqual(fake_assembly.name, resp['name'])
|
||||
|
@ -22,7 +22,7 @@ from solum.tests import fakes
|
||||
|
||||
@mock.patch('pecan.request', new_callable=fakes.FakePecanRequest)
|
||||
@mock.patch('pecan.response', new_callable=fakes.FakePecanResponse)
|
||||
@mock.patch('solum.api.handlers.plan_handler.PlanHandler')
|
||||
@mock.patch('solum.api.handlers.camp.plan_handler.PlanHandler')
|
||||
class TestPlans(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestPlans, self).setUp()
|
||||
@ -33,8 +33,7 @@ class TestPlans(base.BaseTestCase):
|
||||
fake_plan = fakes.FakePlan()
|
||||
hand_get_all.return_value = [fake_plan]
|
||||
|
||||
cont = plans.PlansController()
|
||||
resp = cont.get()
|
||||
resp = plans.PlansController().get()
|
||||
self.assertIsNotNone(resp)
|
||||
self.assertEqual(200, resp_mock.status)
|
||||
self.assertIsNotNone(resp['result'].plan_links)
|
||||
|
Loading…
Reference in New Issue
Block a user