Support retrospective mapping of project type to modules

During its development the module may move from one project type to others
(e.g. in some release it may become incubated or integrated). This patch
adds support of new version of official programs.yaml file
(https://raw.github.com/openstack/governance/master/reference/programs.yaml)
that supports specifying the first version when the module gets promoted up
to the next status.

Closes bug 1308347

Change-Id: I9d83910f209afd81cab94aecac36f4cb08111c35
This commit is contained in:
Ilya Shakhat 2014-04-21 16:01:56 +04:00
parent cf8a9dcc85
commit 34013400e7
13 changed files with 544 additions and 123 deletions

View File

@ -57,27 +57,49 @@ def record_filter(ignore=None, use_default=True):
ignore = []
def decorator(f):
def _filter_records_by_modules(memory_storage_inst, modules, releases):
selected = set([])
for m, r in vault.resolve_modules(modules, releases):
y = memory_storage_inst.get_record_ids_by_modules([m])
if r:
x = memory_storage_inst.get_record_ids_by_releases([r])
selected |= x & y
else:
selected |= y
return selected
@functools.wraps(f)
def record_filter_decorated_function(*args, **kwargs):
memory_storage_inst = vault.get_memory_storage()
record_ids = set(memory_storage_inst.get_record_ids()) # a copy
if 'module' not in ignore:
param = parameters.get_parameter(kwargs, 'module', 'modules',
use_default)
if param:
record_ids &= (
memory_storage_inst.get_record_ids_by_modules(
vault.resolve_modules(param)))
releases = []
if 'release' not in ignore:
releases = parameters.get_parameter(kwargs, 'release',
'releases', use_default)
if releases:
if 'all' not in releases:
record_ids &= (
memory_storage_inst.get_record_ids_by_releases(
c.lower() for c in releases))
modules = parameters.get_parameter(kwargs, 'module', 'modules',
use_default)
if 'project_type' not in ignore:
param = parameters.get_parameter(kwargs, 'project_type',
'project_types', use_default)
if param:
record_ids &= (
memory_storage_inst.get_record_ids_by_modules(
vault.resolve_project_types(param)))
record_ids &= _filter_records_by_modules(
memory_storage_inst,
vault.resolve_project_types(param),
releases)
if 'module' not in ignore:
if modules:
record_ids &= _filter_records_by_modules(
memory_storage_inst, modules, releases)
if 'user_id' not in ignore:
param = parameters.get_parameter(kwargs, 'user_id', 'user_ids')
@ -94,15 +116,6 @@ def record_filter(ignore=None, use_default=True):
record_ids &= (
memory_storage_inst.get_record_ids_by_companies(param))
if 'release' not in ignore:
param = parameters.get_parameter(kwargs, 'release', 'releases',
use_default)
if param:
if 'all' not in param:
record_ids &= (
memory_storage_inst.get_record_ids_by_releases(
c.lower() for c in param))
if 'metric' not in ignore:
metrics = parameters.get_parameter(kwargs, 'metric')
if 'all' not in metrics:

View File

@ -13,11 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import collections
import os
import flask
from oslo.config import cfg
import six
from dashboard import memory_storage
from stackalytics.openstack.common import log as logging
@ -84,40 +84,11 @@ def _init_releases(vault):
vault['releases'] = releases_map
def _make_module(module_id, text, modules, tag):
return {'id': module_id, 'text': text,
'modules': set(modules), 'tag': tag}
def _init_module_groups(vault):
runtime_storage_inst = vault['runtime_storage']
memory_storage_inst = vault['memory_storage']
module_group_index = collections.defaultdict(set)
module_id_index = {}
module_groups = runtime_storage_inst.get_by_key('module_groups') or {}
for module_group in module_groups.values():
module_group_name = module_group['module_group_name']
module_group_id = module_group.get('id') or module_group_name.lower()
module_id_index[module_group_id] = _make_module(
module_group_id, module_group_name, module_group['modules'],
module_group.get('tag') or 'group')
for module in module_group['modules']:
module_group_index[module].add(module_group_id)
for module in memory_storage_inst.get_modules():
module_id_index[module] = _make_module(module.lower(), module,
[module.lower()], 'module')
module_id_index['all'] = _make_module('all', 'All',
memory_storage_inst.get_modules(),
'project_type')
vault['module_group_index'] = module_group_index
vault['module_id_index'] = module_id_index
vault['module_id_index'] = module_groups
def _init_project_types(vault):
@ -184,20 +155,37 @@ def get_user_from_runtime_storage(user_id):
return user_index[user_id]
def resolve_modules(module_ids):
def resolve_modules(module_ids, releases):
module_id_index = get_vault().get('module_id_index') or {}
modules = set()
for module_id in module_ids:
if module_id in module_id_index:
modules |= set(module_id_index[module_id]['modules'])
return modules
module_group = module_id_index[module_id]
if not releases or 'all' in releases:
if 'releases' in module_group:
for release, modules in six.iteritems(
module_group['releases']):
for module in modules:
yield module, release
if 'modules' in module_group:
for module in module_group['modules']:
yield module, None
else:
for release in releases:
if 'releases' in module_group:
for module in module_group['releases'][release]:
yield module, release
if 'modules' in module_group:
for module in module_group['modules']:
yield module, release
def resolve_project_types(project_types):
modules = set()
project_types_index = get_vault()['project_types_index']
for pt in project_types:
pt = pt.lower()
if is_project_type_valid(pt):
modules |= resolve_modules(
get_vault()['project_types_index'][pt]['modules'])
if pt in project_types_index:
modules |= set(project_types_index[pt]['modules'])
return modules

View File

@ -21,7 +21,6 @@ import time
import flask
from flask.ext import gravatar as gravatar_ext
import itertools
from oslo.config import cfg
import six
@ -136,7 +135,7 @@ def get_core_engineer_branch(user, modules):
def get_engineers(records, metric_filter, finalize_handler):
modules_names = parameters.get_parameter({}, 'module', 'modules')
modules = vault.resolve_modules(modules_names)
modules = set([m for m, r in vault.resolve_modules(modules_names, [''])])
def postprocessing(record):
if finalize_handler:
@ -157,7 +156,7 @@ def get_engineers(records, metric_filter, finalize_handler):
@decorators.record_filter(ignore='metric')
def get_engineers_extended(records):
modules_names = parameters.get_parameter({}, 'module', 'modules')
modules = vault.resolve_modules(modules_names)
modules = set([m for m, r in vault.resolve_modules(modules_names, [''])])
def postprocessing(record):
record = decorators.mark_finalize(record)
@ -257,26 +256,24 @@ def get_companies_json(records):
@decorators.exception_handler()
@decorators.record_filter(ignore='module')
def get_modules_json(records):
module_group_index = vault.get_vault()['module_group_index']
module_id_index = vault.get_vault()['module_id_index']
tags = parameters.get_parameter({}, 'tag', 'tags')
# all modules mentioned in records
module_ids = set(record['module'] for record in records)
# plus all module groups that hold these modules
module_ids |= set(itertools.chain.from_iterable(
module_group_index.get(module, []) for module in module_ids))
module_ids = set(record['module'] for record in records
if record['module'] in module_id_index)
add_modules = set([])
for module in six.itervalues(module_id_index):
if set(module['modules']) <= module_ids:
add_modules.add(module['id'])
module_ids |= add_modules
# keep only modules with specified tags
if tags:
module_ids = set(module_id for module_id in module_ids
if module_id_index[module_id].get('tag') in tags)
# keep only modules that are in project type completely
pts = parameters.get_parameter({}, 'project_type', 'project_types')
if pts:
m = set(vault.resolve_project_types(pts))
module_ids = set(module_id for module_id in module_ids
if module_id_index[module_id]['modules'] <= m)
query = (flask.request.args.get('query') or '').lower()
matched = []
@ -286,6 +283,8 @@ def get_modules_json(records):
module = dict([(k, v) for k, v in
six.iteritems(module_id_index[module_id])
if k not in ['modules']])
module['text'] = module['module_group_name']
del module['module_group_name']
matched.append(module)
return sorted(matched, key=operator.itemgetter('text'))
@ -312,7 +311,7 @@ def get_module(module):
module = module.lower()
if module in module_id_index:
return {'id': module_id_index[module]['id'],
'text': module_id_index[module]['text'],
'text': module_id_index[module]['module_group_name'],
'tag': module_id_index[module]['tag']}
flask.abort(404)

326
etc/copy_of_programs.yaml Normal file
View File

@ -0,0 +1,326 @@
Compute:
codename: Nova
ptl: Michael Still (mikal)
mission:
To implement services and associated libraries to provide massively scalable,
on demand, self service access to compute resources, including bare metal,
virtual machines, and containers.
url: https://wiki.openstack.org/wiki/Nova
projects:
- repo: openstack/nova
integrated-since: austin
- repo: openstack/python-novaclient
- repo: openstack/nova-specs
Object Storage:
codename: Swift
ptl: John Dickinson (notmyname)
url: https://wiki.openstack.org/wiki/Swift
projects:
- repo: openstack/swift
integrated-since: austin
- repo: openstack/python-swiftclient
- repo: openstack/swift-bench
Image Service:
codename: Glance
ptl: Mark Washenberger (markwash)
url: https://wiki.openstack.org/wiki/Glance
projects:
- repo: openstack/glance
integrated-since: bexar
- repo: openstack/python-glanceclient
Identity:
codename: Keystone
ptl: Dolph Mathews (dolphm)
mission:
To facilitate API client authentication, service discovery, and distributed
multi-tenant authorization.
url: https://wiki.openstack.org/wiki/Keystone
projects:
- repo: openstack/keystone
integrated-since: essex
- repo: openstack/python-keystoneclient
Dashboard:
codename: Horizon
ptl: David Lyle (david-lyle)
url: https://wiki.openstack.org/wiki/Horizon
projects:
- repo: openstack/horizon
integrated-since: essex
- repo: openstack/django_openstack_auth
- repo: openstack/tuskar-ui
Networking:
codename: Neutron
ptl: Kyle Mestery (mestery)
mission:
To implement services and associated libraries to provide on-demand,
scalable, and technology-agnostic network abstraction.
url: https://wiki.openstack.org/wiki/Neutron
projects:
- repo: openstack/neutron
integrated-since: folsom
- repo: openstack/python-neutronclient
- repo: openstack/neutron-specs
Block Storage:
codename: Cinder
ptl: John Griffith (jgriffith)
mission:
To implement services and libraries to provide on-demand,
self-service access to Block Storage resources via abstraction
and automation on top of other block storage devices.
url: https://wiki.openstack.org/wiki/Cinder
projects:
- repo: openstack/cinder
integrated-since: folsom
- repo: openstack/python-cinderclient
Telemetry:
codename: Ceilometer
ptl : Eoghan Glynn (eglynn)
url: https://wiki.openstack.org/wiki/Ceilometer
projects:
- repo: openstack/ceilometer
incubated-since: grizzly
integrated-since: havana
- repo: openstack/python-ceilometerclient
Orchestration:
codename: Heat
ptl: Zane Bitter (zaneb)
url: https://wiki.openstack.org/wiki/Heat
projects:
- repo: openstack/heat
incubated-since: grizzly
integrated-since: havana
- repo: openstack/python-heatclient
- repo: openstack/heat-cfntools
- repo: openstack/heat-templates
- repo: openstack-dev/heat-cfnclient
Database Service:
codename: Trove
ptl: Nikhil Manchanda (SlickNik)
mission:
To provide scalable and reliable Cloud Database as a Service
functionality for both relational and non-relational database
engines, and to continue to improve its fully-featured and
extensible open source framework.
url: https://wiki.openstack.org/wiki/Trove
projects:
- repo: openstack/trove
incubated-since: havana
integrated-since: icehouse
- repo: openstack/python-troveclient
- repo: openstack/trove-integration
Bare metal:
codename: Ironic
ptl: Devananda van der Veen (devananda)
mission:
To produce an OpenStack service and associated python libraries capable
of managing and provisioning physical machines, and to do this in a
security-aware and fault-tolerant manner.
url: https://wiki.openstack.org/wiki/Ironic
projects:
- repo: openstack/ironic
incubated-since: havana
- repo: openstack/python-ironicclient
- repo: openstack/ironic-python-agent
Common Libraries:
codename: Oslo
ptl: Doug Hellmann (dhellmann)
mission:
To produce a set of python libraries containing code shared by OpenStack
projects. The APIs provided by these libraries should be high quality,
stable, consistent, documented and generally applicable.
url: https://wiki.openstack.org/wiki/Oslo
projects:
- repo: openstack/cliff
- repo: openstack/oslo.config
- repo: openstack/oslo-incubator
- repo: openstack/oslo.messaging
- repo: openstack/oslo.rootwrap
- repo: openstack/oslosphinx
- repo: openstack/oslo.test
- repo: openstack/oslo.version
- repo: openstack/oslo.vmware
- repo: openstack/pycadf
- repo: openstack/stevedore
- repo: openstack/taskflow
- repo: openstack-dev/cookiecutter
- repo: openstack-dev/oslo-cookiecutter
- repo: openstack-dev/hacking
- repo: openstack-dev/pbr
Infrastructure:
ptl: James E. Blair (jeblair)
url: https://wiki.openstack.org/wiki/Infrastructure
mission:
Develop and maintain the tooling and infrastructure needed to
support the development process and general operation of the
OpenStack project.
projects:
- repo: openstack-dev/openstack-nose
- repo: openstack-infra/activity-board
- repo: openstack-infra/askbot-theme
- repo: openstack-infra/config
- repo: openstack-infra/devstack-gate
- repo: openstack-infra/elastic-recheck
- repo: openstack-infra/gear
- repo: openstack-infra/gearman-plugin
- repo: openstack-infra/gerrit
- repo: openstack-infra/gerritbot
- repo: openstack-infra/gerritlib
- repo: openstack-infra/git-review
- repo: openstack-infra/gitdm
- repo: openstack-infra/groups
- repo: openstack-infra/jeepyb
- repo: openstack-infra/jenkins-job-builder
- repo: openstack-infra/lodgeit
- repo: openstack-infra/meetbot
- repo: openstack-infra/nodepool
- repo: openstack-infra/nose-html-output
- repo: openstack-infra/odsreg
- repo: openstack-infra/openstackid
- repo: openstack-infra/os-loganalyze
- repo: openstack-infra/publications
- repo: openstack-infra/puppet-apparmor
- repo: openstack-infra/puppet-dashboard
- repo: openstack-infra/puppet-vcsrepo
- repo: openstack-infra/pypi-mirror
- repo: openstack-infra/releasestatus
- repo: openstack-infra/reviewday
- repo: openstack-infra/reviewstats
- repo: openstack-infra/statusbot
- repo: openstack-infra/storyboard
- repo: openstack-infra/storyboard-webclient
- repo: openstack-infra/tripleo-ci
- repo: openstack-infra/zmq-event-publisher
- repo: openstack-infra/zuul
- repo: openstack-infra/zuul-packaging
- repo: openstack/openstack-planet
Documentation:
ptl: Anne Gentle (annegentle)
mission:
Provide documentation for core OpenStack projects to promote OpenStack.
Develop and maintain tools and processes to ensure quality, accurate
documentation. Treat documentation like OpenStack code.
url: https://wiki.openstack.org/wiki/Documentation
projects:
- repo: openstack/api-site
- repo: openstack/compute-api
- repo: openstack/database-api
- repo: openstack/identity-api
- repo: openstack/image-api
- repo: openstack/netconn-api
- repo: openstack/object-api
- repo: openstack/openstack-doc-tools
- repo: openstack/openstack-manuals
- repo: openstack/operations-guide
- repo: openstack/volume-api
Quality Assurance:
codename: QA
ptl: Matthew Treinish (mtreinish)
mission:
Develop, maintain, and initiate tools and plans to ensure the upstream
stability and quality of OpenStack, and its release readiness at any
point during the release cycle.
url: https://wiki.openstack.org/wiki/QA
projects:
- repo: openstack/tempest
- repo: openstack-dev/grenade
- repo: openstack/qa-specs
Deployment:
codename: TripleO
ptl: Robert Collins (lifeless)
mission:
Develop and maintain tooling and infrastructure able to deploy OpenStack
in production, using OpenStack itself wherever possible.
url: https://wiki.openstack.org/wiki/TripleO
projects:
- repo: openstack/diskimage-builder
- repo: openstack/os-apply-config
- repo: openstack/os-cloud-config
- repo: openstack/os-collect-config
- repo: openstack/os-refresh-config
- repo: openstack/tripleo-heat-templates
- repo: openstack/tripleo-image-elements
- repo: openstack/tripleo-incubator
- repo: openstack/tuskar
- repo: openstack/python-tuskarclient
Devstack:
ptl: Dean Troyer (dtroyer)
mission:
To provide an installation of OpenStack from git repository master, or
specific branches, suitable for development and operational testing.
It also attempts to document the process and provide examples of command
line usage.
url: https://wiki.openstack.org/wiki/DevStack
projects:
- repo: openstack-dev/devstack
Release cycle management:
ptl: Thierry Carrez (ttx)
mission:
To organize the release cycle and the work necessary to produce
coordinated releases of the integrated components of OpenStack.
To collect bugfix backports and produce stable point releases for the
previously-released branch. To coordinate the publication of security
patches and advisories (OSSA) for security-supported branches.
url: https://wiki.openstack.org/wiki/Release_Cycle_Management
projects:
- repo: openstack/requirements
- repo: openstack-infra/release-tools
Queue service:
codename: Marconi
ptl: Kurt Griffiths (kgriffs)
mission:
To produce an OpenStack message queueing API and service that affords
a variety of distributed application messaging patterns in an efficient,
scalable and highly-available manner, and to create and maintain
associated Python libraries and documentation.
url: https://wiki.openstack.org/wiki/Marconi
projects:
- repo: openstack/marconi
incubated-since: icehouse
- repo: openstack/python-marconiclient
Data processing service:
codename: Sahara
ptl: Sergey Lukjanov (SergeyLukjanov)
mission:
To provide a scalable data processing stack and associated management
interfaces.
url: https://wiki.openstack.org/wiki/Sahara
projects:
- repo: openstack/sahara
incubated-since: icehouse
integrated-since: juno
- repo: openstack/python-saharaclient
- repo: openstack/sahara-dashboard
- repo: openstack/sahara-extra
- repo: openstack/sahara-image-elements
Key management service:
codename: Barbican
ptl: Jarret Raim (jraim)
mission:
To produce a secret storage and generation system capable of providing key
management for services wishing to enable encryption features.
url: https://wiki.openstack.org/wiki/Barbican
projects:
- repo: stackforge/barbican
incubated-since: juno
- repo: stackforge/python-barbicanclient

View File

@ -7376,11 +7376,23 @@
"releases": [
{
"release_name": "prehistory",
"end_date": "2011-Apr-21"
"end_date": "2010-Jan-01"
},
{
"release_name": "Austin",
"end_date": "2010-Oct-21"
},
{
"release_name": "Bexar",
"end_date": "2011-Feb-03"
},
{
"release_name": "Cactus",
"end_date": "2011-Apr-15"
},
{
"release_name": "Diablo",
"end_date": "2011-Sep-08"
"end_date": "2011-Sep-22"
},
{
"release_name": "Essex",

View File

@ -3,7 +3,7 @@ Image Service:
ptl: Mark Washenberger (markwash)
url: https://wiki.openstack.org/wiki/Glance
projects:
integrated:
- openstack/glance
other:
- openstack/python-glanceclient
- repo: openstack/glance
integrated-since: havana
incubated-since: grizzly
- repo: openstack/python-glanceclient

View File

@ -138,7 +138,8 @@ def _store_companies(runtime_storage_inst, companies):
def _store_module_groups(runtime_storage_inst, module_groups):
stored_mg = runtime_storage_inst.get_by_key('module_groups') or {}
for mg in module_groups:
stored_mg[mg['module_group_name']] = mg
mg['id'] = mg['module_group_name']
stored_mg[mg['id']] = mg
runtime_storage_inst.set_by_key('module_groups', stored_mg)

View File

@ -194,42 +194,86 @@ def _make_module_group(group_id, name, modules, tag=None):
return module_group
def _read_module_groups(program_list_uri):
def _read_official_programs_yaml(program_list_uri, release_names):
LOG.debug('Process list of programs from uri: %s', program_list_uri)
content = yaml.safe_load(utils.read_uri(program_list_uri))
module_groups = []
modules_by_types = collections.defaultdict(list)
module_groups = collections.defaultdict(
lambda: {'modules': [], 'releases': collections.defaultdict(list)})
official_integrated = module_groups['official-integrated']
official_integrated['tag'] = 'project_type'
official_integrated['module_group_name'] = 'official-integrated'
official_incubated = module_groups['official-incubated']
official_incubated['tag'] = 'project_type'
official_incubated['module_group_name'] = 'official-incubated'
official_other = module_groups['official-other']
official_other['tag'] = 'project_type'
official_other['module_group_name'] = 'official-other'
for name, info in six.iteritems(content):
# for one program
group_id = name.lower()
if 'codename' in info:
name = '%s (%s)' % (info['codename'], name)
group_id = '%s-group' % info['codename'].lower()
all_modules = []
for project_type, project_list in six.iteritems(info['projects']):
module_list = [s.split('/')[1] for s in project_list]
modules_by_types[project_type] += module_list
all_modules += module_list
module_groups[group_id]['module_group_name'] = name
module_groups[group_id]['tag'] = 'program'
module_groups.append(_make_module_group(
group_id, name, all_modules, 'program'))
for module in info['projects']:
module_name = module['repo'].split('/')[1]
module_groups[group_id]['modules'].append(module_name)
if ('integrated-since' in module) or ('incubated-since' in module):
project_type = 'official-other'
for release_name in release_names:
if release_name == module.get('incubated-since'):
project_type = 'official-incubated'
elif release_name == module.get('integrated-since'):
project_type = 'official-integrated'
module_groups[project_type]['releases'][
release_name].append(module_name)
else:
module_groups['official-other']['modules'].append(module_name)
# set ids for module groups
for group_id, group in six.iteritems(module_groups):
group['id'] = group_id
all_modules = []
for project_type, modules_list in six.iteritems(modules_by_types):
all_modules += modules_list
module_groups.append(
_make_module_group(
'official-%s' % project_type, project_type.capitalize(),
modules_list, 'project_type'))
module_groups.append(_make_module_group(
'official-all', 'OpenStack', all_modules, 'project_type'))
return module_groups
def process_program_list(runtime_storage_inst, program_list_uri):
module_groups = runtime_storage_inst.get_by_key('module_groups') or {}
for mg in _read_module_groups(program_list_uri):
module_groups[mg['module_group_name']] = mg
release_names = [r['release_name'].lower()
for r in runtime_storage_inst.get_by_key('releases')[1:]]
official_module_groups = _read_official_programs_yaml(
program_list_uri, release_names)
LOG.debug('Update module groups with official: %s', official_module_groups)
module_groups.update(official_module_groups)
# register modules as module groups
repos = runtime_storage_inst.get_by_key('repos') or []
for repo in repos:
module = repo['module']
module_groups[module] = {
'id': module,
'module_group_name': module,
'modules': [module],
'tag': 'module'
}
# register module 'unknown' - used for emails not mapped to any module
module_groups['unknown'] = {
'id': 'unknown',
'module_group_name': 'unknown',
'modules': ['unknown'],
'tag': 'module'
}
runtime_storage_inst.set_by_key('module_groups', module_groups)

View File

@ -66,6 +66,13 @@ def make_records(**kwargs):
return generate_records
def make_module(module_name):
return {'id': module_name,
'module_group_name': module_name,
'modules': [module_name],
'tag': 'module'}
class TestStorage(runtime_storage.RuntimeStorage):
def __init__(self, data):

View File

@ -34,7 +34,11 @@ class TestAPICompanies(test_api.TestAPI):
],
'module_groups': {
'openstack': {'module_group_name': 'openstack',
'modules': ['nova', 'glance']}
'modules': ['nova', 'glance']},
'nova': {'module_group_name': 'nova',
'modules': ['nova']},
'glance': {'module_group_name': 'glance',
'modules': ['glance']},
}},
test_api.make_records(record_type=['commit'],
loc=[10, 20, 30],

View File

@ -26,9 +26,15 @@ class TestAPIModules(test_api.TestAPI):
'uri': 'git://github.com/openstack/nova.git'},
{'module': 'glance', 'organization': 'openstack',
'uri': 'git://github.com/openstack/glance.git'}],
'module_groups': {'nova-group': {
'module_group_name': 'nova-group',
'modules': ['nova', 'nova-cli']}},
'module_groups': {
'nova-group': {'id': 'nova-group',
'module_group_name': 'nova-group',
'modules': ['nova', 'nova-cli'],
'tag': 'group'},
'nova': test_api.make_module('nova'),
'nova-cli': test_api.make_module('nova-cli'),
'glance': test_api.make_module('glance'),
},
'project_types': [
{'id': 'all', 'title': 'All',
'modules': ['nova', 'glance', 'nova-cli']},
@ -73,9 +79,14 @@ class TestAPIModules(test_api.TestAPI):
with test_api.make_runtime_storage(
{'repos': [{'module': 'nova', 'organization': 'openstack',
'uri': 'git://github.com/openstack/nova.git'}],
'module_groups': {'nova-group': {
'module_group_name': 'nova-group',
'modules': ['nova', 'python-novaclient']}}},
'module_groups': {
'nova-group': {'id': 'nova-group',
'module_group_name': 'nova-group',
'modules': ['nova', 'nova-cli'],
'tag': 'group'},
'nova': test_api.make_module('nova'),
'nova-cli': test_api.make_module('nova-cli'),
}},
test_api.make_records(record_type=['commit'])):
response = self.app.get('/api/1.0/modules/nova')

View File

@ -26,9 +26,14 @@ class TestAPIStats(test_api.TestAPI):
'uri': 'git://github.com/openstack/nova.git'},
{'module': 'glance', 'organization': 'openstack',
'uri': 'git://github.com/openstack/glance.git'}],
'module_groups': {'openstack': {
'module_group_name': 'openstack',
'modules': ['nova', 'glance']}},
'module_groups': {
'openstack': {'id': 'openstack',
'module_group_name': 'openstack',
'modules': ['nova', 'glance'],
'tag': 'group'},
'nova': test_api.make_module('nova'),
'glance': test_api.make_module('glance'),
},
'project_types': [
{'id': 'all', 'title': 'All',
'modules': ['nova', 'glance']}]},
@ -55,9 +60,14 @@ class TestAPIStats(test_api.TestAPI):
{'module': 'glance', 'project_type': 'openstack',
'organization': 'openstack',
'uri': 'git://github.com/openstack/glance.git'}],
'module_groups': {'openstack': {
'module_group_name': 'openstack',
'modules': ['nova', 'glance']}},
'module_groups': {
'openstack': {'id': 'openstack',
'module_group_name': 'openstack',
'modules': ['nova', 'glance'],
'tag': 'group'},
'nova': test_api.make_module('nova'),
'glance': test_api.make_module('glance'),
},
'project_types': [
{'id': 'all', 'title': 'All',
'modules': ['nova', 'glance']}],
@ -98,9 +108,14 @@ class TestAPIStats(test_api.TestAPI):
{'module': 'glance', 'project_type': 'openstack',
'organization': 'openstack',
'uri': 'git://github.com/openstack/glance.git'}],
'module_groups': {'openstack': {
'module_group_name': 'openstack',
'modules': ['nova', 'glance']}},
'module_groups': {
'openstack': {'id': 'openstack',
'module_group_name': 'openstack',
'modules': ['nova', 'glance'],
'tag': 'group'},
'nova': test_api.make_module('nova'),
'glance': test_api.make_module('glance'),
},
'project_types': [
{'id': 'all', 'title': 'All',
'modules': ['nova', 'glance']}],

View File

@ -20,18 +20,16 @@ from tests.api import test_api
class TestAPIUsers(test_api.TestAPI):
def test_users_empty(self):
with test_api.make_runtime_storage({}):
response = self.app.get('/api/1.0/users')
self.assertEqual(200, response.status_code)
def test_users(self):
with test_api.make_runtime_storage(
{'repos': [{'module': 'nova', 'organization': 'openstack',
'uri': 'git://github.com/openstack/nova.git'}],
'project_types': [
{'id': 'openstack', 'title': 'openstack',
'modules': ['nova', 'glance']}]},
'modules': ['nova', 'glance']}],
'module_groups': {
'nova': test_api.make_module('nova'),
'glance': test_api.make_module('glance')}},
test_api.make_records(record_type=['commit'], module=['nova'],
user_id=['john_doe', 'bill_smith'])):
response = self.app.get('/api/1.0/users?'
@ -47,7 +45,10 @@ class TestAPIUsers(test_api.TestAPI):
'uri': 'git://github.com/openstack/nova.git'}],
'project_types': [
{'id': 'openstack', 'title': 'openstack',
'modules': ['nova', 'glance']}]},
'modules': ['nova', 'glance']}],
'module_groups': {
'nova': test_api.make_module('nova'),
'glance': test_api.make_module('glance')}},
test_api.make_records(record_type=['commit'], module=['nova'],
user_name=['John Doe', 'Bill Smith'])):
response = self.app.get('/api/1.0/users?'