Adds Variables support to Projects resource
Includes Variables support, which is already present in several other Craton resources, in the Projects resource as well. Project variables will serve as a top-most scope of variables for resources that belong to a specific project. Partial-Bug: 1648626 Closes-Bug: 1661670 Change-Id: I574e834ce409efd8ceafb15fe30a86ae93df2a80
This commit is contained in:
parent
656535624e
commit
603cef7a31
|
@ -38,6 +38,7 @@ class Projects(base.Resource):
|
|||
@base.http_codes
|
||||
def post(self, context, request_data):
|
||||
"""Create a new project. Requires super admin privileges."""
|
||||
LOG.debug("TEM calling dbapi.projects_create")
|
||||
project_obj = dbapi.projects_create(context, request_data)
|
||||
|
||||
location = v1.api.url_for(
|
||||
|
@ -45,7 +46,13 @@ class Projects(base.Resource):
|
|||
)
|
||||
headers = {'Location': location}
|
||||
|
||||
return jsonutils.to_primitive(project_obj), 201, headers
|
||||
project = jsonutils.to_primitive(project_obj)
|
||||
if 'variables' in request_data:
|
||||
project["variables"] = \
|
||||
jsonutils.to_primitive(project_obj.variables)
|
||||
else:
|
||||
project["variables"] = {}
|
||||
return project, 201, headers
|
||||
|
||||
|
||||
class ProjectById(base.Resource):
|
||||
|
@ -54,7 +61,9 @@ class ProjectById(base.Resource):
|
|||
def get(self, context, id):
|
||||
"""Get a project details by id. Requires super admin privileges."""
|
||||
project_obj = dbapi.projects_get_by_id(context, id)
|
||||
return jsonutils.to_primitive(project_obj), 200, None
|
||||
project = jsonutils.to_primitive(project_obj)
|
||||
project['variables'] = jsonutils.to_primitive(project_obj.variables)
|
||||
return project, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def delete(self, context, id):
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log
|
||||
|
||||
|
||||
from craton.api.v1 import base
|
||||
from craton.api.v1.resources import utils
|
||||
from craton import db as dbapi
|
||||
|
||||
|
||||
# NOTE(thomasem): LOG must exist for craton.api.v1.base module to introspect
|
||||
# and execute this modules LOG.
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class Variables(base.Resource):
|
||||
|
||||
@base.http_codes
|
||||
|
|
|
@ -11,7 +11,7 @@ from craton.api.v1.resources.inventory import networks
|
|||
|
||||
VARS_RESOLVE = ", ".join(map(repr, ("hosts", )))
|
||||
VARS_NOT_RESOLVE = ", ".join(
|
||||
map(repr, ("network-devices", "cells", "regions", "networks"))
|
||||
map(repr, ("network-devices", "cells", "regions", "networks", "projects"))
|
||||
)
|
||||
|
||||
routes = [
|
||||
|
|
|
@ -364,6 +364,7 @@ DefinitionProject = {
|
|||
"name": {
|
||||
"type": "string",
|
||||
},
|
||||
"variables": DefinitionVariablesSource,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -997,6 +998,10 @@ validators = {
|
|||
"type": "integer",
|
||||
"description": "Last project ID of the previous page",
|
||||
},
|
||||
"vars": {
|
||||
"type": "string",
|
||||
"description": "variable filters to get a project",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""SQLAlchemy backend implementation."""
|
||||
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_db import exception as db_exc
|
||||
|
@ -8,7 +9,6 @@ from oslo_db import options as db_options
|
|||
from oslo_db.sqlalchemy import session
|
||||
from oslo_db.sqlalchemy import utils as db_utils
|
||||
from oslo_log import log
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
import sqlalchemy.orm.exc as sa_exc
|
||||
from sqlalchemy.orm import with_polymorphic
|
||||
|
@ -140,6 +140,7 @@ def _get_resource_model(resource):
|
|||
),
|
||||
"networks": models.Network,
|
||||
"regions": models.Region,
|
||||
"projects": models.Project,
|
||||
}
|
||||
return resource_models[resource]
|
||||
|
||||
|
@ -476,29 +477,31 @@ def hosts_labels_delete(context, host_id, labels):
|
|||
return _device_labels_delete(context, 'hosts', host_id, labels)
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def projects_get_all(context, filters, pagination_params):
|
||||
"""Get all the projects."""
|
||||
session = get_session()
|
||||
query = model_query(context, models.Project, session=session)
|
||||
if "vars" in filters:
|
||||
query = add_var_filters_to_query(query, filters)
|
||||
return _paginate(context, query, models.Project, session, filters,
|
||||
pagination_params)
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def projects_get_by_name(context, project_name):
|
||||
def projects_get_by_name(context, project_name, filters, pagination_params):
|
||||
"""Get all projects that match the given name."""
|
||||
query = model_query(context, models.Project)
|
||||
query = query.filter(models.Project.name.like(project_name))
|
||||
if "vars" in filters:
|
||||
query = add_var_filters_to_query(query, filters)
|
||||
try:
|
||||
return query.all()
|
||||
return _paginate(context, query, models.Project, session, filters,
|
||||
pagination_params)
|
||||
except sa_exc.NoResultFound:
|
||||
raise exceptions.NotFound()
|
||||
except Exception as err:
|
||||
raise exceptions.UnknownException(message=err)
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def projects_get_by_id(context, project_id):
|
||||
"""Get project by its id."""
|
||||
query = model_query(context, models.Project)
|
||||
|
@ -514,10 +517,11 @@ def projects_get_by_id(context, project_id):
|
|||
@require_admin_context
|
||||
def projects_create(context, values):
|
||||
"""Create a new project with given values."""
|
||||
LOG.debug("TEM: uuid = {}".format(type(uuid)))
|
||||
session = get_session()
|
||||
project = models.Project()
|
||||
if not values.get('id'):
|
||||
values['id'] = uuidutils.generate_uuid()
|
||||
values['id'] = uuid.uuid4()
|
||||
with session.begin():
|
||||
project.update(values)
|
||||
project.save(session)
|
||||
|
|
|
@ -227,7 +227,7 @@ class VariableMixin(object):
|
|||
return blamed
|
||||
|
||||
|
||||
class Project(Base):
|
||||
class Project(Base, VariableMixin):
|
||||
"""Supports multitenancy for all other schema elements."""
|
||||
__tablename__ = 'projects'
|
||||
id = Column(UUIDType(binary=False), primary_key=True)
|
||||
|
@ -359,12 +359,12 @@ class Device(Base, VariableMixin):
|
|||
|
||||
@property
|
||||
def resolution_order(self):
|
||||
# TODO(jimbaker) add self.project to resolution_order
|
||||
return list(itertools.chain(
|
||||
[self],
|
||||
self.ancestors,
|
||||
[self.cell] if self.cell else [],
|
||||
[self.region]))
|
||||
[self.region],
|
||||
[self.project]))
|
||||
|
||||
__mapper_args__ = {
|
||||
'polymorphic_on': type,
|
||||
|
|
|
@ -26,4 +26,5 @@ class TestCase(testtools.TestCase):
|
|||
self.context = make_context(auth_token='fake-token',
|
||||
user='fake-user',
|
||||
tenant='fake-tenant',
|
||||
is_admin=True)
|
||||
is_admin=True,
|
||||
is_admin_project=True)
|
||||
|
|
|
@ -12,6 +12,13 @@ FAKE_DATA_GEN_USERNAME = 'demo'
|
|||
FAKE_DATA_GEN_TOKEN = 'demo'
|
||||
FAKE_DATA_GEN_PROJECT_ID = 'b9f10eca66ac4c279c139d01e65f96b4'
|
||||
|
||||
FAKE_DATA_GEN_BOOTSTRAP_USERNAME = 'bootstrap'
|
||||
FAKE_DATA_GEN_BOOTSTRAP_TOKEN = 'bootstrap'
|
||||
|
||||
HEADER_TOKEN = 'X-Auth-Token'
|
||||
HEADER_USERNAME = 'X-Auth-User'
|
||||
HEADER_PROJECT = 'X-Auth-Project'
|
||||
|
||||
|
||||
class DockerSetup(threading.Thread):
|
||||
|
||||
|
@ -148,17 +155,27 @@ def setup_database(container_ip):
|
|||
# isolate all test from any external scripts.
|
||||
projects = meta.tables['projects']
|
||||
users = meta.tables['users']
|
||||
variable_assn = meta.tables['variable_association']
|
||||
|
||||
with contextlib.closing(engine.connect()) as conn:
|
||||
transaction = conn.begin()
|
||||
result = conn.execute(variable_assn.insert(),
|
||||
discriminator='project')
|
||||
conn.execute(projects.insert(),
|
||||
name=FAKE_DATA_GEN_USERNAME,
|
||||
id=FAKE_DATA_GEN_PROJECT_ID)
|
||||
id=FAKE_DATA_GEN_PROJECT_ID,
|
||||
variable_association_id=result.inserted_primary_key[0])
|
||||
conn.execute(users.insert(),
|
||||
project_id=FAKE_DATA_GEN_PROJECT_ID,
|
||||
username=FAKE_DATA_GEN_USERNAME,
|
||||
api_key=FAKE_DATA_GEN_TOKEN,
|
||||
is_admin=True)
|
||||
conn.execute(users.insert(),
|
||||
project_id=FAKE_DATA_GEN_PROJECT_ID,
|
||||
username=FAKE_DATA_GEN_BOOTSTRAP_USERNAME,
|
||||
api_key=FAKE_DATA_GEN_BOOTSTRAP_TOKEN,
|
||||
is_admin=True,
|
||||
is_root=True)
|
||||
transaction.commit()
|
||||
|
||||
|
||||
|
@ -173,9 +190,9 @@ class TestCase(testtools.TestCase):
|
|||
data = _container.container_data
|
||||
self.service_ip = data['NetworkSettings']['IPAddress']
|
||||
self.url = 'http://{}:8080'.format(self.service_ip)
|
||||
self.session.headers['X-Auth-Project'] = FAKE_DATA_GEN_PROJECT_ID
|
||||
self.session.headers['X-Auth-Token'] = FAKE_DATA_GEN_TOKEN
|
||||
self.session.headers['X-Auth-User'] = FAKE_DATA_GEN_USERNAME
|
||||
self.session.headers[HEADER_PROJECT] = FAKE_DATA_GEN_PROJECT_ID
|
||||
self.session.headers[HEADER_USERNAME] = FAKE_DATA_GEN_USERNAME
|
||||
self.session.headers[HEADER_TOKEN] = FAKE_DATA_GEN_TOKEN
|
||||
|
||||
setup_database(self.service_ip)
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class APIV1CellTest(APIV1ResourceWithVariablesTestCase):
|
|||
self.assertEqual('cell-a', cell['name'])
|
||||
self.assertEqual(variables, cell['variables'])
|
||||
|
||||
def test_create_region_supports_vars_ops(self):
|
||||
def test_create_cell_supports_vars_ops(self):
|
||||
cell = self.create_cell('new-cell', {'a': 'b'})
|
||||
self.assert_vars_get_expected(cell['id'], {'a': 'b'})
|
||||
self.assert_vars_can_be_set(cell['id'])
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
import copy
|
||||
|
||||
from craton.tests import functional
|
||||
from craton.tests.functional.test_variable_calls import \
|
||||
APIV1ResourceWithVariablesTestCase
|
||||
|
||||
|
||||
class ProjectTests(functional.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ProjectTests, self).setUp()
|
||||
self.root_headers = copy.deepcopy(self.session.headers)
|
||||
self.root_headers[functional.HEADER_USERNAME] = \
|
||||
functional.FAKE_DATA_GEN_BOOTSTRAP_USERNAME
|
||||
self.root_headers[functional.HEADER_TOKEN] = \
|
||||
functional.FAKE_DATA_GEN_BOOTSTRAP_TOKEN
|
||||
|
||||
def tearDown(self):
|
||||
super(ProjectTests, self).tearDown()
|
||||
|
||||
def create_project(self, name, variables=None):
|
||||
url = self.url + '/v1/projects'
|
||||
payload = {'name': name}
|
||||
if variables:
|
||||
payload['variables'] = variables
|
||||
project = self.post(url, headers=self.root_headers, data=payload)
|
||||
self.assertEqual(201, project.status_code)
|
||||
self.assertIn('Location', project.headers)
|
||||
self.assertEqual(
|
||||
project.headers['Location'],
|
||||
"{}/{}".format(url, project.json()['id'])
|
||||
)
|
||||
|
||||
return project.json()
|
||||
|
||||
|
||||
class TestPaginationOfProjects(ProjectTests):
|
||||
def setUp(self):
|
||||
super(TestPaginationOfProjects, self).setUp()
|
||||
self.projects = [
|
||||
self.create_project('project-{}'.format(i))
|
||||
for i in range(0, 61)
|
||||
]
|
||||
|
||||
def test_lists_first_thirty_projects(self):
|
||||
response = self.get(self.url + '/v1/projects')
|
||||
self.assertSuccessOk(response)
|
||||
json = response.json()
|
||||
self.assertIn('projects', json)
|
||||
projects = json['projects']
|
||||
self.assertEqual(30, len(projects))
|
||||
|
||||
|
||||
class APIV1ProjectTest(ProjectTests, APIV1ResourceWithVariablesTestCase):
|
||||
|
||||
resource = 'projects'
|
||||
|
||||
def test_project_create_with_variables(self):
|
||||
variables = {'a': 'b'}
|
||||
project_name = 'test'
|
||||
project = self.create_project(project_name, variables=variables)
|
||||
self.assertEqual(project_name, project['name'])
|
||||
self.assertEqual(variables, project['variables'])
|
||||
|
||||
def test_create_project_supports_vars_ops(self):
|
||||
project = self.create_project('test', {'a': 'b'})
|
||||
self.assert_vars_get_expected(project['id'], {'a': 'b'})
|
||||
self.assert_vars_can_be_set(project['id'])
|
||||
self.assert_vars_can_be_deleted(project['id'])
|
||||
|
||||
def test_project_create_with_duplicate_name_works(self):
|
||||
project_name = 'test'
|
||||
self.create_project(project_name)
|
||||
url = self.url + '/v1/projects'
|
||||
payload = {'name': project_name}
|
||||
project = self.post(url, headers=self.root_headers, data=payload)
|
||||
self.assertEqual(201, project.status_code)
|
||||
|
||||
def test_project_get_all_with_name_filter(self):
|
||||
proj1 = 'test1'
|
||||
proj2 = 'test2'
|
||||
self.create_project(proj2)
|
||||
for i in range(3):
|
||||
self.create_project(proj1)
|
||||
url = self.url + '/v1/projects?name={}'.format(proj1)
|
||||
resp = self.get(url, headers=self.root_headers)
|
||||
projects = resp.json()['projects']
|
||||
self.assertEqual(3, len(projects))
|
||||
for project in projects:
|
||||
self.assertEqual(proj1, project['name'])
|
||||
|
||||
def test_get_project_details(self):
|
||||
project_name = 'test'
|
||||
project_vars = {"who": "that"}
|
||||
project = self.create_project(project_name, variables=project_vars)
|
||||
url = self.url + '/v1/projects/{}'.format(project['id'])
|
||||
project_with_detail = self.get(url, headers=self.root_headers)
|
||||
self.assertEqual(project_name, project_with_detail.json()['name'])
|
||||
self.assertEqual(project_vars, project_with_detail.json()['variables'])
|
||||
|
||||
def test_project_delete(self):
|
||||
project1 = self.create_project('test1')
|
||||
url = self.url + '/v1/projects'
|
||||
projects = self.get(url, headers=self.root_headers)
|
||||
# NOTE(thomasem): Have to include the default project created by
|
||||
# test setup.
|
||||
self.assertEqual(2, len(projects.json()['projects']))
|
||||
|
||||
delurl = self.url + '/v1/projects/{}'.format(project1['id'])
|
||||
self.delete(delurl, headers=self.root_headers)
|
||||
|
||||
projects = self.get(url, headers=self.root_headers)
|
||||
self.assertEqual(1, len(projects.json()['projects']))
|
||||
|
||||
def test_project_variables_update(self):
|
||||
project_name = 'test'
|
||||
project = self.create_project(project_name)
|
||||
variables = {"bumbleywump": "cucumberpatch"}
|
||||
|
||||
put_url = self.url + '/v1/projects/{}/variables'.format(project['id'])
|
||||
resp = self.put(put_url, headers=self.root_headers, data=variables)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
get_url = self.url + '/v1/projects/{}'.format(project['id'])
|
||||
project = self.get(get_url, headers=self.root_headers)
|
||||
self.assertEqual(variables, project.json()['variables'])
|
||||
|
||||
def test_project_variables_delete(self):
|
||||
project_name = 'test'
|
||||
delete_key = 'bumbleywump'
|
||||
variables = {
|
||||
delete_key: 'cucumberpatch'
|
||||
}
|
||||
expected_vars = {'foo': 'bar'}
|
||||
variables.update(expected_vars)
|
||||
|
||||
project = self.create_project(project_name, variables=variables)
|
||||
self.assert_vars_get_expected(project['id'], variables)
|
||||
self.assert_vars_can_be_deleted(project['id'])
|
|
@ -11,30 +11,37 @@ default_pagination = {'limit': 30, 'marker': None}
|
|||
|
||||
class HostsDBTestCase(base.DBTestCase):
|
||||
|
||||
project_id = uuid.uuid4().hex
|
||||
mock_project_id = uuid.uuid4().hex
|
||||
|
||||
def make_region(self, name, **variables):
|
||||
def make_project(self, name, **variables):
|
||||
project = dbapi.projects_create(
|
||||
self.context,
|
||||
{"name": name,
|
||||
"variables": variables})
|
||||
return str(project.id)
|
||||
|
||||
def make_region(self, project_id, name, **variables):
|
||||
region = dbapi.regions_create(
|
||||
self.context,
|
||||
{'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'variables': variables})
|
||||
return region.id
|
||||
|
||||
def make_cell(self, region_id, name, **variables):
|
||||
def make_cell(self, project_id, region_id, name, **variables):
|
||||
cell = dbapi.cells_create(
|
||||
self.context,
|
||||
{'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'region_id': region_id,
|
||||
'variables': variables})
|
||||
return cell.id
|
||||
|
||||
def make_host(self, region_id, name, ip_address, host_type, cell_id=None,
|
||||
parent_id=None, labels=None, **variables):
|
||||
def make_host(self, project_id, region_id, name, ip_address, host_type,
|
||||
cell_id=None, parent_id=None, labels=None, **variables):
|
||||
if cell_id:
|
||||
host = {'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'region_id': region_id,
|
||||
'cell_id': cell_id,
|
||||
'ip_address': ip_address,
|
||||
|
@ -45,7 +52,7 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
'variables': variables}
|
||||
else:
|
||||
host = {'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'region_id': region_id,
|
||||
'ip_address': ip_address,
|
||||
'parent_id': parent_id,
|
||||
|
@ -58,24 +65,26 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
return host.id
|
||||
|
||||
def make_very_small_cloud(self, with_cell=False):
|
||||
project_id = self.make_project('project_1', foo='P1', zoo='P2')
|
||||
region_id = self.make_region(
|
||||
project_id,
|
||||
'region_1',
|
||||
foo='R1', bar='R2', bax='R3')
|
||||
if with_cell:
|
||||
cell_id = self.make_cell(region_id, 'cell_1', bar='C2')
|
||||
cell_id = self.make_cell(project_id, region_id, 'cell_1', bar='C2')
|
||||
else:
|
||||
cell_id = None
|
||||
host_id = self.make_host(region_id, 'www1.example.com',
|
||||
host_id = self.make_host(project_id, region_id, 'www1.example.com',
|
||||
IPAddress(u'10.1.2.101'), 'server',
|
||||
cell_id=cell_id, foo='H1', baz='H3')
|
||||
return region_id, cell_id, host_id
|
||||
return project_id, region_id, cell_id, host_id
|
||||
|
||||
def test_hosts_create(self):
|
||||
# Need to do this query despite creation above because other
|
||||
# elements (cell, region) were in separate committed sessions
|
||||
# when the host was created. Verify these linked elements load
|
||||
# correctly
|
||||
region_id, cell_id, host_id = self.make_very_small_cloud(
|
||||
project_id, region_id, cell_id, host_id = self.make_very_small_cloud(
|
||||
with_cell=True)
|
||||
host = dbapi.hosts_get_by_id(self.context, host_id)
|
||||
self.assertEqual(host.region.id, region_id)
|
||||
|
@ -86,36 +95,40 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
# Verify resolved variables/blames override properly
|
||||
self.assertEqual(
|
||||
[obj.id for obj in host.resolution_order],
|
||||
[host_id, cell_id, region_id])
|
||||
[host_id, cell_id, region_id, uuid.UUID(project_id)])
|
||||
|
||||
self.assertEqual(
|
||||
[variables for variables in host.resolution_order_variables],
|
||||
[{'foo': 'H1', 'baz': 'H3'},
|
||||
{'bar': 'C2'},
|
||||
{'foo': 'R1', 'bar': 'R2', 'bax': 'R3'}])
|
||||
{'foo': 'R1', 'bar': 'R2', 'bax': 'R3'},
|
||||
{'foo': 'P1', 'zoo': 'P2'}])
|
||||
|
||||
self.assertEqual(
|
||||
host.resolved,
|
||||
{'foo': 'H1', 'bar': 'C2', 'baz': 'H3', 'bax': 'R3'})
|
||||
{'foo': 'H1', 'bar': 'C2', 'baz': 'H3', 'bax': 'R3', 'zoo': 'P2'})
|
||||
|
||||
blame = host.blame(['foo', 'bar'])
|
||||
blame = host.blame(['foo', 'bar', 'zoo'])
|
||||
self.assertEqual(blame['foo'].source.name, 'www1.example.com')
|
||||
self.assertEqual(blame['foo'].variable.value, 'H1')
|
||||
self.assertEqual(blame['bar'].source.name, 'cell_1')
|
||||
self.assertEqual(blame['bar'].variable.value, 'C2')
|
||||
self.assertEqual(blame['zoo'].source.name, 'project_1')
|
||||
self.assertEqual(blame['zoo'].variable.value, 'P2')
|
||||
|
||||
def test_hosts_create_duplicate_raises(self):
|
||||
region_id = self.make_region('region_1')
|
||||
self.make_host(region_id, 'www1.example.com',
|
||||
region_id = self.make_region(self.mock_project_id, 'region_1')
|
||||
self.make_host(self.mock_project_id, region_id, 'www1.example.com',
|
||||
IPAddress(u'10.1.2.101'), 'server')
|
||||
new_host = {'name': 'www1.example.com', 'region_id': region_id,
|
||||
'ip_address': IPAddress(u'10.1.2.101'),
|
||||
'device_type': 'server', 'project_id': self.project_id}
|
||||
'device_type': 'server',
|
||||
'project_id': self.mock_project_id}
|
||||
self.assertRaises(exceptions.DuplicateDevice, dbapi.hosts_create,
|
||||
self.context, new_host)
|
||||
|
||||
def test_hosts_create_without_cell(self):
|
||||
region_id, _, host_id = self.make_very_small_cloud()
|
||||
project_id, region_id, _, host_id = self.make_very_small_cloud()
|
||||
host = dbapi.hosts_get_by_id(self.context, host_id)
|
||||
self.assertEqual(host.region.id, region_id)
|
||||
self.assertEqual(host.region.name, 'region_1')
|
||||
|
@ -124,26 +137,29 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
# Verify resolved variables/blames override properly
|
||||
self.assertEqual(
|
||||
[obj.id for obj in host.resolution_order],
|
||||
[host_id, region_id])
|
||||
[host_id, region_id, uuid.UUID(project_id)])
|
||||
|
||||
self.assertEqual(
|
||||
[variables for variables in host.resolution_order_variables],
|
||||
[{'foo': 'H1', 'baz': 'H3'},
|
||||
{'foo': 'R1', 'bar': 'R2', 'bax': 'R3'}])
|
||||
{'foo': 'R1', 'bar': 'R2', 'bax': 'R3'},
|
||||
{'foo': 'P1', 'zoo': 'P2'}])
|
||||
|
||||
self.assertEqual(
|
||||
host.resolved,
|
||||
{'foo': 'H1', 'bar': 'R2', 'baz': 'H3', 'bax': 'R3'})
|
||||
{'foo': 'H1', 'bar': 'R2', 'baz': 'H3', 'bax': 'R3', 'zoo': 'P2'})
|
||||
|
||||
blame = host.blame(['foo', 'bar'])
|
||||
blame = host.blame(['foo', 'bar', 'zoo'])
|
||||
self.assertEqual(blame['foo'].source.name, 'www1.example.com')
|
||||
self.assertEqual(blame['foo'].variable.value, 'H1')
|
||||
self.assertEqual(blame['bar'].source.name, 'region_1')
|
||||
self.assertEqual(blame['bar'].variable.value, 'R2')
|
||||
self.assertEqual(blame['zoo'].source.name, 'project_1')
|
||||
self.assertEqual(blame['zoo'].variable.value, 'P2')
|
||||
|
||||
def test_hosts_update(self):
|
||||
region_id = self.make_region('region_1')
|
||||
host_id = self.make_host(region_id, 'example',
|
||||
region_id = self.make_region(self.mock_project_id, 'region_1')
|
||||
host_id = self.make_host(self.mock_project_id, region_id, 'example',
|
||||
IPAddress(u'10.1.2.101'), 'server',
|
||||
bar='bar2')
|
||||
name = "Host_New"
|
||||
|
@ -151,14 +167,19 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
self.assertEqual(res.name, name)
|
||||
|
||||
def test_hosts_variable_resolved_with_parent(self):
|
||||
project_id = self.make_project(
|
||||
'project_1',
|
||||
foo='P1', zoo='P2')
|
||||
region_id = self.make_region(
|
||||
project_id,
|
||||
'region_1',
|
||||
foo='R1', bar='R2', bax='R3')
|
||||
cell_id = self.make_cell(region_id, 'cell_1', bar='C2')
|
||||
host1_id = self.make_host(region_id, 'www1.example.com',
|
||||
cell_id = self.make_cell(project_id, region_id, 'cell_1',
|
||||
bar='C2')
|
||||
host1_id = self.make_host(project_id, region_id, 'www1.example.com',
|
||||
IPAddress(u'10.1.2.101'), 'server',
|
||||
cell_id=cell_id, foo='H1', baz='H3')
|
||||
host2_id = self.make_host(region_id, 'www1.example2.com',
|
||||
host2_id = self.make_host(project_id, region_id, 'www1.example2.com',
|
||||
IPAddress(u'10.1.2.102'), 'server',
|
||||
cell_id=cell_id, parent_id=host1_id)
|
||||
host2 = dbapi.hosts_get_by_id(self.context, host2_id)
|
||||
|
@ -166,28 +187,32 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
# Verify resolved variables/blames override properly
|
||||
self.assertEqual(
|
||||
[obj.id for obj in host2.resolution_order],
|
||||
[host2_id, host1_id, cell_id, region_id])
|
||||
[host2_id, host1_id, cell_id, region_id, uuid.UUID(project_id)])
|
||||
|
||||
self.assertEqual(
|
||||
[variables for variables in host2.resolution_order_variables],
|
||||
[{},
|
||||
{'baz': 'H3', 'foo': 'H1'},
|
||||
{'bar': 'C2'},
|
||||
{'bar': 'R2', 'foo': 'R1', 'bax': 'R3'}])
|
||||
{'bar': 'R2', 'foo': 'R1', 'bax': 'R3'},
|
||||
{'foo': 'P1', 'zoo': 'P2'}])
|
||||
|
||||
self.assertEqual(
|
||||
host2.resolved,
|
||||
{'foo': 'H1', 'bar': 'C2', 'baz': 'H3', 'bax': 'R3'})
|
||||
{'foo': 'H1', 'bar': 'C2', 'baz': 'H3', 'bax': 'R3', 'zoo': 'P2'})
|
||||
|
||||
blame = host2.blame(['foo', 'bar'])
|
||||
blame = host2.blame(['foo', 'bar', 'zoo'])
|
||||
self.assertEqual(blame['foo'].source.name, 'www1.example.com')
|
||||
self.assertEqual(blame['foo'].variable.value, 'H1')
|
||||
self.assertEqual(blame['bar'].source.name, 'cell_1')
|
||||
self.assertEqual(blame['bar'].variable.value, 'C2')
|
||||
self.assertEqual(blame['zoo'].source.name, 'project_1')
|
||||
self.assertEqual(blame['zoo'].variable.value, 'P2')
|
||||
|
||||
def test_hosts_variables_no_resolved(self):
|
||||
region_id = self.make_region('region_1', foo='R1')
|
||||
host_id = self.make_host(region_id, 'www.example.xyz',
|
||||
project_id = self.make_project('project_1', zoo='P2')
|
||||
region_id = self.make_region(project_id, 'region_1', foo='R1')
|
||||
host_id = self.make_host(project_id, region_id, 'www.example.xyz',
|
||||
IPAddress(u'10.1.2.101'),
|
||||
'server', bar='bar2')
|
||||
host = dbapi.hosts_get_by_id(self.context, host_id)
|
||||
|
@ -195,8 +220,11 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
self.assertEqual(host.variables, {'bar': 'bar2'})
|
||||
|
||||
def test_hosts_resolved_vars_no_cells(self):
|
||||
region_id = self.make_region('region_1', foo='R1')
|
||||
host_id = self.make_host(region_id, 'www.example.xyz',
|
||||
project_id = self.make_project('project_1')
|
||||
region_id = self.make_region(project_id, 'region_1',
|
||||
foo='R1')
|
||||
host_id = self.make_host(project_id, region_id,
|
||||
'www.example.xyz',
|
||||
IPAddress(u'10.1.2.101'),
|
||||
'server', bar='bar2')
|
||||
host = dbapi.hosts_get_by_id(self.context, host_id)
|
||||
|
@ -204,16 +232,20 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
self.assertEqual(host.resolved, {'bar': 'bar2', 'foo': 'R1'})
|
||||
|
||||
def test_host_labels_create(self):
|
||||
region_id = self.make_region('region_1', foo='R1')
|
||||
host_id = self.make_host(region_id, 'www.example.xyz',
|
||||
region_id = self.make_region(self.mock_project_id, 'region_1',
|
||||
foo='R1')
|
||||
host_id = self.make_host(self.mock_project_id, region_id,
|
||||
'www.example.xyz',
|
||||
IPAddress(u'10.1.2.101'),
|
||||
'server', bar='bar2')
|
||||
labels = {"labels": ["tom", "jerry"]}
|
||||
dbapi.hosts_labels_update(self.context, host_id, labels)
|
||||
|
||||
def test_host_labels_delete(self):
|
||||
region_id = self.make_region('region_1', foo='R1')
|
||||
host_id = self.make_host(region_id, 'www.example.xyz',
|
||||
region_id = self.make_region(self.mock_project_id, 'region_1',
|
||||
foo='R1')
|
||||
host_id = self.make_host(self.mock_project_id, region_id,
|
||||
'www.example.xyz',
|
||||
IPAddress(u'10.1.2.101'),
|
||||
'server', bar='bar2')
|
||||
_labels = {"labels": ["tom", "jerry", "jones"]}
|
||||
|
@ -226,12 +258,14 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
self.assertEqual(host.labels, {"jerry", "jones"})
|
||||
|
||||
def test_hosts_get_all_with_filter_cell_id(self):
|
||||
region_id = self.make_region('region_1', foo='R1')
|
||||
cell_id1 = self.make_cell(region_id, 'cell_1', bar='C2')
|
||||
cell_id2 = self.make_cell(region_id, 'cell_2', bar='C2')
|
||||
project_id = self.make_project('project_1', foo='P1', zoo='P2')
|
||||
region_id = self.make_region(project_id, 'region_1', foo='R1')
|
||||
cell_id1 = self.make_cell(project_id, region_id, 'cell_1', bar='C2')
|
||||
cell_id2 = self.make_cell(project_id, region_id, 'cell_2', bar='C2')
|
||||
self.assertNotEqual(cell_id1, cell_id2)
|
||||
|
||||
self.make_host(
|
||||
project_id,
|
||||
region_id,
|
||||
'www.example.xyz',
|
||||
IPAddress(u'10.1.2.101'),
|
||||
|
@ -239,6 +273,7 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
cell_id=cell_id1,
|
||||
)
|
||||
self.make_host(
|
||||
project_id,
|
||||
region_id,
|
||||
'www.example.abc',
|
||||
IPAddress(u'10.1.2.102'),
|
||||
|
@ -261,8 +296,9 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
self.assertEqual(res[0].name, 'www.example.xyz')
|
||||
|
||||
def test_hosts_get_all_with_filters(self):
|
||||
region_id = self.make_region('region_1', foo='R1')
|
||||
host_id = self.make_host(region_id, 'www.example.xyz',
|
||||
project_id = self.make_project('project_1', foo='P1', zoo='P2')
|
||||
region_id = self.make_region(project_id, 'region_1', foo='R1')
|
||||
host_id = self.make_host(project_id, region_id, 'www.example.xyz',
|
||||
IPAddress(u'10.1.2.101'),
|
||||
'server')
|
||||
variables = {"key1": "value1", "key2": "value2"}
|
||||
|
@ -279,8 +315,9 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
self.assertEqual(res[0].name, 'www.example.xyz')
|
||||
|
||||
def test_hosts_get_with_key_value_filters(self):
|
||||
region_id = self.make_region('region_1', foo='R1')
|
||||
host1 = self.make_host(region_id, 'www.example.xyz',
|
||||
project_id = self.make_project('project_1', foo='P1', zoo='P2')
|
||||
region_id = self.make_region(project_id, 'region_1', foo='R1')
|
||||
host1 = self.make_host(project_id, region_id, 'www.example.xyz',
|
||||
IPAddress(u'10.1.2.101'),
|
||||
'server')
|
||||
variables = {"key1": "example1", "key2": "Tom"}
|
||||
|
@ -288,7 +325,7 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
self.context, "hosts", host1, variables
|
||||
)
|
||||
# Second host with own variables
|
||||
host2 = self.make_host(region_id, 'www.example2.xyz',
|
||||
host2 = self.make_host(project_id, region_id, 'www.example2.xyz',
|
||||
IPAddress(u'10.1.2.102'),
|
||||
'server')
|
||||
variables = {"key1": "example2", "key2": "Tom"}
|
||||
|
@ -306,8 +343,9 @@ class HostsDBTestCase(base.DBTestCase):
|
|||
self.assertEqual(len(res), 2)
|
||||
|
||||
def test_hosts_get_all_with_filters_noexist(self):
|
||||
region_id = self.make_region('region_1', foo='R1')
|
||||
host_id = self.make_host(region_id, 'www.example.xyz',
|
||||
project_id = self.make_project('project_1', foo='P1', zoo='P2')
|
||||
region_id = self.make_region(project_id, 'region_1', foo='R1')
|
||||
host_id = self.make_host(project_id, region_id, 'www.example.xyz',
|
||||
IPAddress(u'10.1.2.101'),
|
||||
'server')
|
||||
variables = {"key1": "value1", "key2": "value2"}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from oslo_utils import uuidutils
|
||||
import copy
|
||||
import uuid
|
||||
|
||||
from craton import exceptions
|
||||
from craton.db import api as dbapi
|
||||
|
@ -14,39 +15,73 @@ class ProjectsDBTestCase(base.DBTestCase):
|
|||
|
||||
def test_create_project(self):
|
||||
# Set root, as only admin project can create other projects
|
||||
self.context.is_admin_project = True
|
||||
project = dbapi.projects_create(self.context, project1)
|
||||
self.assertTrue(uuidutils.is_uuid_like(project['id']))
|
||||
self.assertEqual(project['name'], project1['name'])
|
||||
|
||||
def test_create_project_no_root_fails(self):
|
||||
context = copy.deepcopy(self.context)
|
||||
context.is_admin_project = False
|
||||
self.assertRaises(exceptions.AdminRequired,
|
||||
dbapi.projects_create,
|
||||
self.context,
|
||||
context,
|
||||
project1)
|
||||
|
||||
def test_project_get_all(self):
|
||||
self.context.is_admin_project = True
|
||||
dbapi.projects_create(self.context, project1)
|
||||
dbapi.projects_create(self.context, project2)
|
||||
|
||||
res = dbapi.projects_get_all(self.context, {}, default_pagination)
|
||||
res, _ = dbapi.projects_get_all(self.context, {}, default_pagination)
|
||||
self.assertEqual(len(res), 2)
|
||||
|
||||
def test_project_get_no_admin_project_raises(self):
|
||||
self.context.is_admin_project = True
|
||||
def test_project_get_by_name(self):
|
||||
dbapi.projects_create(self.context, project1)
|
||||
dbapi.projects_create(self.context, project2)
|
||||
|
||||
# Now set admin_project = false to become normal project user
|
||||
self.context.is_admin_project = False
|
||||
self.assertRaises(exceptions.AdminRequired,
|
||||
dbapi.projects_get_all,
|
||||
self.context,
|
||||
{}, default_pagination)
|
||||
res, _ = dbapi.projects_get_by_name(self.context, project1['name'], {},
|
||||
default_pagination)
|
||||
self.assertEqual(len(res), 1)
|
||||
self.assertEqual(res[0].name, project1['name'])
|
||||
|
||||
def test_project_get_by_id(self):
|
||||
self.context.is_admin_project = True
|
||||
project = dbapi.projects_create(self.context, project1)
|
||||
res = dbapi.projects_get_by_id(self.context, project['id'])
|
||||
self.assertEqual(str(res['id']), project['id'])
|
||||
self.assertEqual(str(res['id']), str(project['id']))
|
||||
|
||||
def test_project_create_id_uuid_type(self):
|
||||
project = dbapi.projects_create(self.context, project1)
|
||||
self.assertEqual(type(project['id']), uuid.UUID)
|
||||
|
||||
def test_project_get_id_uuid_type(self):
|
||||
project = dbapi.projects_create(self.context, project1)
|
||||
res = dbapi.projects_get_by_id(self.context, project['id'])
|
||||
self.assertEqual(type(res['id']), uuid.UUID)
|
||||
|
||||
def test_project_variables_update_does_update_variables(self):
|
||||
create_res = dbapi.projects_create(self.context, project1)
|
||||
res = dbapi.projects_get_by_id(self.context, create_res.id)
|
||||
self.assertEqual(res.variables, {})
|
||||
variables = {"key1": "value1", "key2": "value2"}
|
||||
res = dbapi.variables_update_by_resource_id(
|
||||
self.context, "projects", res.id, variables
|
||||
)
|
||||
self.assertEqual(res.variables, variables)
|
||||
new_variables = {"key1": "tom", "key2": "cat"}
|
||||
res = dbapi.variables_update_by_resource_id(
|
||||
self.context, "projects", res.id, new_variables
|
||||
)
|
||||
self.assertEqual(res.variables, new_variables)
|
||||
|
||||
def test_project_variables_delete(self):
|
||||
create_res = dbapi.projects_create(self.context, project1)
|
||||
res = dbapi.projects_get_by_id(self.context, create_res.id)
|
||||
self.assertEqual(res.variables, {})
|
||||
variables = {"key1": "value1", "key2": "value2"}
|
||||
res = dbapi.variables_update_by_resource_id(
|
||||
self.context, "projects", res.id, variables
|
||||
)
|
||||
self.assertEqual(res.variables, variables)
|
||||
# NOTE(sulo): we delete variables by their key
|
||||
res = dbapi.variables_delete_by_resource_id(
|
||||
self.context, "projects", res.id, {"key1": "key1"}
|
||||
)
|
||||
self.assertEqual(res.variables, {"key2": "value2"})
|
||||
|
|
|
@ -6,25 +6,40 @@ from craton.tests.unit.db import base
|
|||
|
||||
|
||||
class VariablesDBTestCase:
|
||||
project_id = "5a4e32e1-8571-4c2c-a088-a11f98900355"
|
||||
|
||||
def create_region(self, name, variables=None):
|
||||
def _get_mock_resource_id(self):
|
||||
# NOTE(thomasem): Project IDs are UUIDs not integers
|
||||
if self.resources_type in ("projects",):
|
||||
return "5a4e32e1-8571-4c2c-a088-a11f98900355"
|
||||
return 1
|
||||
|
||||
def create_project(self, name, variables=None):
|
||||
project = dbapi.projects_create(
|
||||
self.context,
|
||||
{
|
||||
"name": name,
|
||||
"variables": variables or {},
|
||||
},
|
||||
)
|
||||
return project.id
|
||||
|
||||
def create_region(self, name, project_id, variables=None):
|
||||
region = dbapi.regions_create(
|
||||
self.context,
|
||||
{
|
||||
'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'variables': variables or {},
|
||||
},
|
||||
)
|
||||
return region.id
|
||||
|
||||
def create_cell(self, name, region_id, variables=None):
|
||||
def create_cell(self, name, project_id, region_id, variables=None):
|
||||
cell = dbapi.cells_create(
|
||||
self.context,
|
||||
{
|
||||
'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'region_id': region_id,
|
||||
'variables': variables or {}
|
||||
},
|
||||
|
@ -32,12 +47,12 @@ class VariablesDBTestCase:
|
|||
return cell.id
|
||||
|
||||
def create_host(
|
||||
self, name, region_id, ip_address, host_type, cell_id=None,
|
||||
parent_id=None, labels=None, variables=None,
|
||||
self, name, project_id, region_id, ip_address, host_type,
|
||||
cell_id=None, parent_id=None, labels=None, variables=None,
|
||||
):
|
||||
host = {
|
||||
'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'region_id': region_id,
|
||||
'cell_id': cell_id,
|
||||
'ip_address': ip_address,
|
||||
|
@ -54,12 +69,12 @@ class VariablesDBTestCase:
|
|||
return host.id
|
||||
|
||||
def create_network(
|
||||
self, name, region_id, cidr, gateway, netmask, cell_id=None,
|
||||
variables=None,
|
||||
self, name, project_id, region_id, cidr, gateway, netmask,
|
||||
cell_id=None, variables=None,
|
||||
):
|
||||
network = {
|
||||
'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'region_id': region_id,
|
||||
'cell_id': cell_id,
|
||||
'cidr': cidr,
|
||||
|
@ -74,12 +89,12 @@ class VariablesDBTestCase:
|
|||
return network.id
|
||||
|
||||
def create_network_device(
|
||||
self, name, region_id, ip_address, network_device_type,
|
||||
self, name, project_id, region_id, ip_address, network_device_type,
|
||||
cell_id=None, parent_id=None, labels=None, variables=None,
|
||||
):
|
||||
network_device = {
|
||||
'name': name,
|
||||
'project_id': self.project_id,
|
||||
'project_id': project_id,
|
||||
'region_id': region_id,
|
||||
'cell_id': cell_id,
|
||||
'ip_address': ip_address,
|
||||
|
@ -98,10 +113,13 @@ class VariablesDBTestCase:
|
|||
return network_device.id
|
||||
|
||||
def setup_host(self, variables):
|
||||
region_id = self.create_region(name='region1')
|
||||
cell_id = self.create_cell(name="cell1", region_id=region_id)
|
||||
project_id = self.create_project(name='project1')
|
||||
region_id = self.create_region(name='region1', project_id=project_id)
|
||||
cell_id = self.create_cell(name="cell1", project_id=project_id,
|
||||
region_id=region_id)
|
||||
host_id = self.create_host(
|
||||
name="host1",
|
||||
project_id=project_id,
|
||||
region_id=region_id,
|
||||
ip_address="192.168.2.1",
|
||||
host_type="server",
|
||||
|
@ -114,10 +132,13 @@ class VariablesDBTestCase:
|
|||
return host_id
|
||||
|
||||
def setup_network_device(self, variables):
|
||||
region_id = self.create_region(name='region1')
|
||||
cell_id = self.create_cell(name="cell1", region_id=region_id)
|
||||
project_id = self.create_project(name='project1')
|
||||
region_id = self.create_region(name='region1', project_id=project_id)
|
||||
cell_id = self.create_cell(name="cell1", project_id=project_id,
|
||||
region_id=region_id)
|
||||
network_device_id = self.create_network_device(
|
||||
name="network_device1",
|
||||
project_id=project_id,
|
||||
region_id=region_id,
|
||||
ip_address="192.168.2.1",
|
||||
network_device_type="switch",
|
||||
|
@ -130,10 +151,13 @@ class VariablesDBTestCase:
|
|||
return network_device_id
|
||||
|
||||
def setup_network(self, variables):
|
||||
region_id = self.create_region(name='region1')
|
||||
cell_id = self.create_cell(name="cell1", region_id=region_id)
|
||||
project_id = self.create_project(name='project1')
|
||||
region_id = self.create_region(name='region1', project_id=project_id)
|
||||
cell_id = self.create_cell(name="cell1", project_id=project_id,
|
||||
region_id=region_id)
|
||||
network_id = self.create_network(
|
||||
name="network1",
|
||||
project_id=project_id,
|
||||
region_id=region_id,
|
||||
cell_id=cell_id,
|
||||
cidr="192.168.2.0/24",
|
||||
|
@ -145,9 +169,11 @@ class VariablesDBTestCase:
|
|||
return network_id
|
||||
|
||||
def setup_cell(self, variables):
|
||||
region_id = self.create_region(name='region1')
|
||||
project_id = self.create_project(name='project1')
|
||||
region_id = self.create_region(name='region1', project_id=project_id)
|
||||
cell_id = self.create_cell(
|
||||
name="cell1",
|
||||
project_id=project_id,
|
||||
region_id=region_id,
|
||||
variables=variables,
|
||||
)
|
||||
|
@ -155,13 +181,19 @@ class VariablesDBTestCase:
|
|||
return cell_id
|
||||
|
||||
def setup_region(self, variables):
|
||||
project_id = self.create_project(name='project1')
|
||||
region_id = self.create_region(
|
||||
name='region1',
|
||||
project_id=project_id,
|
||||
variables=variables,
|
||||
)
|
||||
|
||||
return region_id
|
||||
|
||||
def setup_project(self, variables):
|
||||
project_id = self.create_project(name='project1', variables=variables)
|
||||
return project_id
|
||||
|
||||
def setup_resource(self, *args, **kwargs):
|
||||
setup_fn = {
|
||||
"cells": self.setup_cell,
|
||||
|
@ -169,6 +201,7 @@ class VariablesDBTestCase:
|
|||
"networks": self.setup_network,
|
||||
"network-devices": self.setup_network_device,
|
||||
"regions": self.setup_region,
|
||||
"projects": self.setup_project,
|
||||
}
|
||||
|
||||
return setup_fn[self.resources_type](*args, *kwargs)
|
||||
|
@ -196,7 +229,7 @@ class VariablesDBTestCase:
|
|||
dbapi.resource_get_by_id,
|
||||
context=self.context,
|
||||
resources=self.resources_type,
|
||||
resource_id=1,
|
||||
resource_id=self._get_mock_resource_id(),
|
||||
)
|
||||
|
||||
def test_variables_update_by_resource_id_existing_empty(self):
|
||||
|
@ -225,13 +258,12 @@ class VariablesDBTestCase:
|
|||
self.assertEqual(variables, validate.variables)
|
||||
|
||||
def test_variables_update_by_resource_id_not_found(self):
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.NotFound,
|
||||
dbapi.variables_update_by_resource_id,
|
||||
context=self.context,
|
||||
resources=self.resources_type,
|
||||
resource_id=1,
|
||||
resource_id=self._get_mock_resource_id(),
|
||||
data={"key1": "value1"},
|
||||
)
|
||||
|
||||
|
@ -309,7 +341,7 @@ class VariablesDBTestCase:
|
|||
dbapi.variables_delete_by_resource_id,
|
||||
context=self.context,
|
||||
resources=self.resources_type,
|
||||
resource_id=1,
|
||||
resource_id=self._get_mock_resource_id(),
|
||||
data={"key1": "value1"},
|
||||
)
|
||||
|
||||
|
@ -364,3 +396,7 @@ class RegionsVariablesDBTestCase(VariablesDBTestCase, base.DBTestCase):
|
|||
|
||||
class NetworksVariablesDBTestCase(VariablesDBTestCase, base.DBTestCase):
|
||||
resources_type = "networks"
|
||||
|
||||
|
||||
class ProjectsVariablesDBTestCase(VariablesDBTestCase, base.DBTestCase):
|
||||
resources_type = "projects"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import copy
|
||||
import uuid
|
||||
|
||||
|
||||
"""
|
||||
|
@ -8,16 +9,19 @@ objects for test.
|
|||
|
||||
|
||||
class Project(object):
|
||||
def __init__(self, id, name):
|
||||
self.id = id
|
||||
def __init__(self, id, name, variables):
|
||||
self.id = uuid.UUID(id)
|
||||
self.name = name
|
||||
self.variables = variables
|
||||
|
||||
def items(self):
|
||||
return iter(self.__dict__.items())
|
||||
|
||||
|
||||
PROJECT1 = Project("4534dcb4-dacd-474f-8afc-8bd5ab2d26e8", "project1")
|
||||
PROJECT2 = Project("77c527cb-837d-4fcb-bafb-af37ba3d13a4", "project2")
|
||||
PROJECT1 = Project("4534dcb4-dacd-474f-8afc-8bd5ab2d26e8",
|
||||
"project1", {"key1": "value1", "key2": "value2"})
|
||||
PROJECT2 = Project("77c527cb-837d-4fcb-bafb-af37ba3d13a4",
|
||||
"project2", {"key1": "value1", "key2": "value2"})
|
||||
|
||||
|
||||
class User(object):
|
||||
|
|
|
@ -817,6 +817,95 @@ class APIV1ProjectsTest(APIV1Test):
|
|||
resp = self.get('v1/projects')
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
|
||||
@mock.patch.object(dbapi, 'projects_get_by_id')
|
||||
def test_project_get_by_id(self, mock_project):
|
||||
proj1 = fake_resources.PROJECT1
|
||||
proj1_id = str(proj1.id)
|
||||
mock_project.return_value = proj1
|
||||
|
||||
resp = self.get('v1/projects/{}'.format(proj1_id))
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.json['id'], proj1_id)
|
||||
|
||||
@mock.patch.object(dbapi, 'projects_get_by_name')
|
||||
def test_project_get_by_name(self, mock_projects):
|
||||
proj1 = fake_resources.PROJECT1
|
||||
proj1_id = str(proj1.id)
|
||||
return_value = ([proj1], {})
|
||||
mock_projects.return_value = return_value
|
||||
|
||||
resp = self.get('v1/projects?name=project1')
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
projects = resp.json['projects']
|
||||
self.assertEqual(len(projects), 1)
|
||||
self.assertEqual(projects[0]['id'], proj1_id)
|
||||
|
||||
|
||||
class APIV1ProjectsVariablesTest(APIV1Test):
|
||||
@mock.patch.object(dbapi, 'resource_get_by_id')
|
||||
def test_projects_get_variables(self, mock_project):
|
||||
mock_project.return_value = fake_resources.PROJECT1
|
||||
resp = self.get(
|
||||
'v1/projects/{}/variables'.format(fake_resources.PROJECT1.id)
|
||||
)
|
||||
expected = {"variables": {"key1": "value1", "key2": "value2"}}
|
||||
self.assertEqual(resp.json, expected)
|
||||
|
||||
@mock.patch.object(dbapi, 'variables_update_by_resource_id')
|
||||
def test_projects_put_variables(self, mock_project):
|
||||
proj1 = fake_resources.PROJECT1
|
||||
proj1_id = str(proj1.id)
|
||||
db_return_value = copy.deepcopy(proj1)
|
||||
db_return_value.variables["a"] = "b"
|
||||
mock_project.return_value = db_return_value
|
||||
payload = {"a": "b"}
|
||||
db_data = payload.copy()
|
||||
resp = self.put(
|
||||
'v1/projects/{}/variables'.format(proj1_id),
|
||||
data=payload
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
mock_project.assert_called_once_with(mock.ANY, "projects", proj1_id,
|
||||
db_data)
|
||||
expected = {
|
||||
"variables": {"key1": "value1", "key2": "value2", "a": "b"},
|
||||
}
|
||||
self.assertDictEqual(expected, resp.json)
|
||||
|
||||
@mock.patch.object(dbapi, 'variables_update_by_resource_id')
|
||||
def test_projects_put_variables_bad_data_type(self, mock_project):
|
||||
payload = ["a", "b"]
|
||||
resp = self.put(
|
||||
'v1/projects/{}/variables'.format(fake_resources.PROJECT1.id),
|
||||
data=payload
|
||||
)
|
||||
self.assertEqual(400, resp.status_code)
|
||||
mock_project.assert_not_called()
|
||||
|
||||
@mock.patch.object(dbapi, 'variables_delete_by_resource_id')
|
||||
def test_projects_delete_variables(self, mock_project):
|
||||
proj1 = fake_resources.PROJECT1
|
||||
proj1_id = str(proj1.id)
|
||||
payload = ["key1"]
|
||||
db_data = payload.copy()
|
||||
resp = self.delete(
|
||||
'v1/projects/{}/variables'.format(proj1_id), data=payload
|
||||
)
|
||||
self.assertEqual(resp.status_code, 204)
|
||||
mock_project.assert_called_once_with(mock.ANY, "projects", proj1_id,
|
||||
db_data)
|
||||
|
||||
@mock.patch.object(dbapi, 'variables_delete_by_resource_id')
|
||||
def test_projects_delete_variables_bad_data_type(self, mock_project):
|
||||
payload = {'a': 'b'}
|
||||
resp = self.delete(
|
||||
'v1/projects/{}/variables'.format(fake_resources.PROJECT1.id),
|
||||
data=payload
|
||||
)
|
||||
self.assertEqual(400, resp.status_code)
|
||||
mock_project.assert_not_called()
|
||||
|
||||
|
||||
class APIV1UsersTest(APIV1Test):
|
||||
@mock.patch.object(dbapi, 'users_create')
|
||||
|
|
|
@ -23,11 +23,18 @@ USERNAME="demo"
|
|||
TOKEN="demo"
|
||||
PROJECT="b9f10eca66ac4c279c139d01e65f96b4"
|
||||
|
||||
###################################
|
||||
# Create initial project and user #
|
||||
###################################
|
||||
mysql -u root craton -e "INSERT into projects (created_at, updated_at, name, id) values (NOW(), NOW(), '$USERNAME', '$PROJECT')"
|
||||
BOOTSTRAP_USERNAME="bootstrap"
|
||||
BOOTSTRAP_TOKEN="bootstrap"
|
||||
|
||||
PROJECT_DISCRIMINATOR='project'
|
||||
|
||||
####################################
|
||||
# Create initial project and users #
|
||||
####################################
|
||||
PROJECT_VA_ID=$(mysql -u root craton -e "INSERT into variable_association (created_at, updated_at, discriminator) values (NOW(), NOW(), '$PROJECT_DISCRIMINATOR'); SELECT LAST_INSERT_ID();" | grep -Eo '[0-9]+')
|
||||
mysql -u root craton -e "INSERT into projects (created_at, updated_at, name, variable_association_id, id) values (NOW(), NOW(), '$USERNAME', $PROJECT_VA_ID, '$PROJECT')"
|
||||
mysql -u root craton -e "INSERT into users (created_at, updated_at, project_id, username, api_key, is_admin) values (NOW(), NOW(), '$PROJECT', '$USERNAME', '$TOKEN', False)"
|
||||
mysql -u root craton -e "INSERT into users (created_at, updated_at, project_id, username, api_key, is_root, is_admin) values (NOW(), NOW(), '$PROJECT', '$BOOTSTRAP_USERNAME', '$BOOTSTRAP_TOKEN', True, True)"
|
||||
|
||||
#########################
|
||||
# Start the API service #
|
||||
|
|
Loading…
Reference in New Issue