2018-06-15 08:41:24 +02:00
|
|
|
from __future__ import print_function
|
|
|
|
|
2017-05-02 18:11:40 -05:00
|
|
|
from datetime import datetime, timedelta
|
2014-02-25 10:58:21 +01:00
|
|
|
import os
|
2014-06-03 18:05:05 +02:00
|
|
|
import re
|
|
|
|
import string
|
2014-03-04 16:32:15 +01:00
|
|
|
import time
|
2018-11-17 10:01:41 +01:00
|
|
|
|
2018-11-16 08:32:25 +01:00
|
|
|
try:
|
2018-11-17 10:01:41 +01:00
|
|
|
from urllib.parse import unquote, urlparse, urlencode, parse_qs, urljoin
|
2018-11-16 08:32:25 +01:00
|
|
|
except ImportError:
|
|
|
|
# python 2.x
|
2018-11-17 10:01:41 +01:00
|
|
|
from urllib import unquote, urlencode
|
|
|
|
from urlparse import urlparse, urljoin, parse_qs
|
2018-11-16 08:32:25 +01:00
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
import xml.etree.cElementTree as ET
|
2014-02-25 10:58:21 +01:00
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
import httpretty
|
2014-02-25 10:58:21 +01:00
|
|
|
import osc
|
2017-01-09 21:49:50 -06:00
|
|
|
from osclib.cache import Cache
|
2018-09-04 15:03:03 -05:00
|
|
|
from osclib.cache_manager import CacheManager
|
2014-02-25 10:58:21 +01:00
|
|
|
|
2014-02-28 11:45:06 +01:00
|
|
|
|
2015-08-06 13:48:07 +02:00
|
|
|
APIURL = 'http://localhost'
|
2017-05-02 18:10:59 -05:00
|
|
|
PROJECT = 'openSUSE:Factory'
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
FIXTURES = os.path.join(os.getcwd(), 'tests/fixtures')
|
|
|
|
|
2018-11-10 11:29:24 +01:00
|
|
|
DEBUG = False
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
# The idiotic routing system of httpretty use a hash table. Because
|
|
|
|
# we have a default() handler, we need a deterministic routing
|
|
|
|
# mechanism.
|
|
|
|
_table = {
|
|
|
|
httpretty.GET: [],
|
|
|
|
httpretty.POST: [],
|
|
|
|
httpretty.PUT: [],
|
|
|
|
httpretty.DELETE: [],
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def router_handler(route_table, method, request, uri, headers):
|
|
|
|
"""Route the URLs in a deterministic way."""
|
2018-11-17 10:01:41 +01:00
|
|
|
uri_parsed = urlparse(uri)
|
2014-06-03 18:05:05 +02:00
|
|
|
for path, fn in route_table:
|
|
|
|
match = False
|
2018-06-15 08:41:24 +02:00
|
|
|
if not isinstance(path, str):
|
|
|
|
print(path.pattern)
|
|
|
|
if isinstance(path, str) and uri_parsed.path == path:
|
2014-06-03 18:05:05 +02:00
|
|
|
match = True
|
2018-06-15 08:41:24 +02:00
|
|
|
elif not isinstance(path, str) and path.search(uri_parsed.path):
|
2014-06-03 18:05:05 +02:00
|
|
|
match = True
|
|
|
|
if match:
|
|
|
|
return fn(request, uri, headers)
|
|
|
|
raise Exception('Not found entry for method %s for url %s' % (method, uri))
|
|
|
|
|
|
|
|
|
|
|
|
def router_handler_GET(request, uri, headers):
|
|
|
|
return router_handler(_table[httpretty.GET], 'GET', request, uri, headers)
|
|
|
|
|
|
|
|
|
|
|
|
def router_handler_POST(request, uri, headers):
|
|
|
|
return router_handler(_table[httpretty.POST], 'POST', request, uri, headers)
|
|
|
|
|
|
|
|
|
|
|
|
def router_handler_PUT(request, uri, headers):
|
|
|
|
return router_handler(_table[httpretty.PUT], 'PUT', request, uri, headers)
|
|
|
|
|
|
|
|
|
|
|
|
def router_handler_DELETE(request, uri, headers):
|
|
|
|
return router_handler(_table[httpretty.DELETE], 'DELETE', request, uri, headers)
|
|
|
|
|
|
|
|
|
|
|
|
def method_decorator(method, path):
|
|
|
|
def _decorator(fn):
|
|
|
|
def _fn(*args, **kwargs):
|
|
|
|
return fn(OBS._self, *args, **kwargs)
|
|
|
|
_table[method].append((path, _fn))
|
|
|
|
return _fn
|
|
|
|
return _decorator
|
|
|
|
|
|
|
|
|
|
|
|
def GET(path):
|
|
|
|
return method_decorator(httpretty.GET, path)
|
|
|
|
|
|
|
|
|
|
|
|
def POST(path):
|
|
|
|
return method_decorator(httpretty.POST, path)
|
|
|
|
|
|
|
|
|
|
|
|
def PUT(path):
|
|
|
|
return method_decorator(httpretty.PUT, path)
|
|
|
|
|
|
|
|
|
|
|
|
def DELETE(path):
|
|
|
|
return method_decorator(httpretty.DELETE, path)
|
2014-02-25 10:58:21 +01:00
|
|
|
|
2014-03-05 16:22:14 +01:00
|
|
|
|
|
|
|
class OBS(object):
|
2014-06-03 18:05:05 +02:00
|
|
|
# This class will become a singleton
|
|
|
|
_self = None
|
|
|
|
|
|
|
|
def __new__(cls, *args, **kwargs):
|
|
|
|
"""Class constructor."""
|
2014-10-08 14:31:55 +02:00
|
|
|
if not OBS._self:
|
|
|
|
OBS._self = super(OBS, cls).__new__(cls, *args, **kwargs)
|
|
|
|
|
|
|
|
httpretty.reset()
|
|
|
|
httpretty.enable()
|
|
|
|
|
|
|
|
httpretty.register_uri(httpretty.GET, re.compile(r'.*'), body=router_handler_GET)
|
|
|
|
httpretty.register_uri(httpretty.POST, re.compile(r'.*'), body=router_handler_POST)
|
|
|
|
httpretty.register_uri(httpretty.PUT, re.compile(r'.*'), body=router_handler_PUT)
|
|
|
|
httpretty.register_uri(httpretty.DELETE, re.compile(r'.*'), body=router_handler_DELETE)
|
|
|
|
|
|
|
|
return OBS._self
|
2014-02-25 10:58:21 +01:00
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
def __init__(self, fixtures=FIXTURES):
|
|
|
|
"""Instance constructor."""
|
|
|
|
self.fixtures = fixtures
|
2014-02-25 10:58:21 +01:00
|
|
|
|
2018-09-05 23:58:51 -05:00
|
|
|
CacheManager.test = True
|
2018-09-04 15:03:03 -05:00
|
|
|
Cache.init()
|
2017-10-23 23:00:44 -05:00
|
|
|
Cache.delete_all()
|
2014-06-03 18:05:05 +02:00
|
|
|
httpretty.enable()
|
|
|
|
|
|
|
|
oscrc = os.path.join(fixtures, 'oscrc')
|
2014-02-25 10:58:21 +01:00
|
|
|
osc.core.conf.get_config(override_conffile=oscrc,
|
|
|
|
override_no_keyring=True,
|
|
|
|
override_no_gnome_keyring=True)
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
# Internal status of OBS. The mockup will use this data to
|
|
|
|
# build the responses. We will try to put responses as XML
|
|
|
|
# templates in the fixture directory.
|
2017-05-01 22:31:36 -05:00
|
|
|
self.dashboard = {}
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
self.requests = {
|
|
|
|
'123': {
|
|
|
|
'request': 'new',
|
|
|
|
'review': 'accepted',
|
|
|
|
'who': 'Admin',
|
|
|
|
'by': 'group',
|
|
|
|
'id': '123',
|
|
|
|
'by_who': 'opensuse-review-team',
|
|
|
|
'package': 'gcc',
|
|
|
|
},
|
|
|
|
'321': {
|
|
|
|
'request': 'review',
|
|
|
|
'review': 'new',
|
|
|
|
'who': 'Admin',
|
|
|
|
'by': 'group',
|
|
|
|
'id': '321',
|
|
|
|
'by_who': 'factory-staging',
|
|
|
|
'package': 'puppet',
|
|
|
|
},
|
|
|
|
'333': {
|
|
|
|
'request': 'review',
|
|
|
|
'review': 'new',
|
|
|
|
'who': 'Admin',
|
|
|
|
'by': 'project',
|
|
|
|
'id': '333',
|
|
|
|
'by_who': 'openSUSE:Factory:Staging:B',
|
|
|
|
'package': 'wine',
|
|
|
|
},
|
2014-06-16 17:15:24 +02:00
|
|
|
'501': {
|
|
|
|
'request': 'review',
|
|
|
|
'review': 'new',
|
|
|
|
'who': 'Admin',
|
|
|
|
'by': 'project',
|
|
|
|
'id': '501',
|
|
|
|
'by_who': 'openSUSE:Factory:Staging:C',
|
|
|
|
'package': 'apparmor',
|
|
|
|
},
|
|
|
|
'502': {
|
|
|
|
'request': 'review',
|
|
|
|
'review': 'new',
|
|
|
|
'who': 'Admin',
|
|
|
|
'by': 'project',
|
|
|
|
'id': '502',
|
|
|
|
'by_who': 'openSUSE:Factory:Staging:C',
|
|
|
|
'package': 'mariadb',
|
|
|
|
},
|
2014-06-24 14:11:06 +02:00
|
|
|
'1000': {
|
|
|
|
'request': 'review',
|
|
|
|
'review': 'new',
|
|
|
|
'who': 'Admin',
|
|
|
|
'by': 'user',
|
|
|
|
'id': '1000',
|
|
|
|
'by_who': 'factory-repo-checker',
|
|
|
|
'package': 'emacs',
|
|
|
|
},
|
|
|
|
'1001': {
|
|
|
|
'request': 'review',
|
|
|
|
'review': 'new',
|
|
|
|
'who': 'Admin',
|
|
|
|
'by': 'user',
|
|
|
|
'id': '1001',
|
|
|
|
'by_who': 'factory-repo-checker',
|
|
|
|
'package': 'python',
|
|
|
|
},
|
2014-03-05 16:22:14 +01:00
|
|
|
}
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
self.staging_project = {
|
|
|
|
'A': {
|
|
|
|
'project': 'openSUSE:Factory:Staging:A',
|
|
|
|
'title': '',
|
|
|
|
'description': '',
|
|
|
|
},
|
|
|
|
'U': {
|
|
|
|
'project': 'openSUSE:Factory:Staging:U',
|
|
|
|
'title': 'Unfrozen',
|
|
|
|
'description': '',
|
|
|
|
},
|
|
|
|
'B': {
|
|
|
|
'project': 'openSUSE:Factory:Staging:B',
|
|
|
|
'title': 'wine',
|
|
|
|
'description': 'requests:\n- {id: 333, package: wine}',
|
|
|
|
},
|
2014-06-16 17:15:24 +02:00
|
|
|
'C': {
|
|
|
|
'project': 'openSUSE:Factory:Staging:C',
|
|
|
|
'title': 'A project ready to be accepted',
|
2017-09-26 19:03:22 +08:00
|
|
|
'description': ('requests:\n- {id: 501, package: apparmor, author: Admin, type: submit}\n'
|
2018-06-15 08:41:24 +02:00
|
|
|
'- {id: 502, package: mariadb, author: Admin, type: submit}'),
|
2014-06-24 14:11:06 +02:00
|
|
|
},
|
|
|
|
'J': {
|
|
|
|
'project': 'openSUSE:Factory:Staging:J',
|
|
|
|
'title': 'A project to be checked',
|
|
|
|
'description': ('requests:\n- {id: 1000, package: emacs, author: Admin}\n'
|
|
|
|
'- {id: 1001, package: python, author: Admin}'),
|
2014-06-16 17:15:24 +02:00
|
|
|
},
|
2014-03-05 16:22:14 +01:00
|
|
|
}
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
self.links = {
|
2014-03-05 16:22:14 +01:00
|
|
|
'openSUSE:Factory:Staging:B/wine': {
|
2014-06-03 18:05:05 +02:00
|
|
|
'prj': 'openSUSE:Factory:Staging:B',
|
|
|
|
'pkg': 'wine',
|
|
|
|
'devprj': 'home:Admin',
|
|
|
|
},
|
2014-06-16 17:15:24 +02:00
|
|
|
'openSUSE:Factory:Staging:C/apparmor': {
|
|
|
|
'prj': 'openSUSE:Factory:Staging:C',
|
|
|
|
'pkg': 'apparmor',
|
|
|
|
'devprj': 'home:Admin',
|
|
|
|
},
|
|
|
|
'openSUSE:Factory:Staging:C/mariadb': {
|
|
|
|
'prj': 'openSUSE:Factory:Staging:C',
|
|
|
|
'pkg': 'mariadb',
|
|
|
|
'devprj': 'home:Admin',
|
|
|
|
},
|
2014-06-24 14:11:06 +02:00
|
|
|
'openSUSE:Factory:Staging:J/emacs': {
|
|
|
|
'prj': 'openSUSE:Factory:Staging:J',
|
|
|
|
'pkg': 'emacs',
|
2014-06-25 14:17:52 +02:00
|
|
|
'devprj': 'home:Admin',
|
2014-06-24 14:11:06 +02:00
|
|
|
},
|
|
|
|
'openSUSE:Factory:Staging:J/python': {
|
|
|
|
'prj': 'openSUSE:Factory:Staging:J',
|
|
|
|
'pkg': 'python',
|
2014-06-25 14:17:52 +02:00
|
|
|
'devprj': 'home:Admin',
|
2014-06-24 14:11:06 +02:00
|
|
|
},
|
2014-03-07 13:58:33 +01:00
|
|
|
}
|
2014-06-03 18:05:05 +02:00
|
|
|
|
2018-06-15 08:41:24 +02:00
|
|
|
self.attributes = {
|
|
|
|
'openSUSE:Factory': {
|
|
|
|
'OSRT': {
|
|
|
|
'Config': 'overridden-by-local = remote-nope\n'
|
2018-08-16 21:54:20 -05:00
|
|
|
'remote-only = remote-indeed\n'
|
2018-06-15 08:41:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-01 17:10:36 -05:00
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
self.meta = {}
|
|
|
|
|
|
|
|
self.package = {
|
|
|
|
'home:Admin/gcc': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'gcc',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
|
|
|
'home:Admin/wine': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'wine',
|
2014-06-17 14:39:51 +02:00
|
|
|
'srcmd5': 'de9a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
|
|
|
'home:Admin/puppet': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'puppet',
|
|
|
|
'srcmd5': 'de8a9f5e3bedb01980465f3be3d236cb',
|
2014-06-03 18:05:05 +02:00
|
|
|
},
|
|
|
|
'openSUSE:Factory/gcc': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'gcc',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
|
|
|
'openSUSE:Factory/wine': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'wine',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
|
|
|
'openSUSE:Factory:Rings:0-Bootstrap/elem-ring0': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'elem-ring0',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
|
|
|
'openSUSE:Factory/binutils': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'wine',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
2014-06-16 17:15:24 +02:00
|
|
|
'home:Admin/apparmor': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'apparmor',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
|
|
|
'openSUSE:Factory/apparmor': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'apparmor',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
|
|
|
'home:Admin/mariadb': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'mariadb',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
|
|
|
'openSUSE:Factory/mariadb': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'mariadb',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
},
|
2014-06-25 14:17:52 +02:00
|
|
|
'home:Admin/emacs': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'emacs',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
2014-07-04 15:20:28 +02:00
|
|
|
'lsrcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
'verifymd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
2014-06-25 14:17:52 +02:00
|
|
|
},
|
|
|
|
'home:Admin/python': {
|
|
|
|
'rev': '1',
|
|
|
|
'vrev': '1',
|
|
|
|
'name': 'python',
|
|
|
|
'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
2014-07-04 15:20:28 +02:00
|
|
|
'lsrcmd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
|
|
|
'verifymd5': 'de7a9f5e3bedb01980465f3be3d236cb',
|
2014-06-25 14:17:52 +02:00
|
|
|
},
|
2014-03-05 16:22:14 +01:00
|
|
|
}
|
2014-02-27 13:39:57 +01:00
|
|
|
|
2014-06-04 16:54:21 +02:00
|
|
|
self.comments = {
|
|
|
|
'openSUSE:Factory:Staging:A': [
|
2014-06-23 14:08:00 +02:00
|
|
|
{
|
|
|
|
'who': 'Admin',
|
|
|
|
'when': '2014-06-01 17:56:28 UTC',
|
|
|
|
'id': '1',
|
|
|
|
'body': 'Just a comment',
|
2014-06-04 16:54:21 +02:00
|
|
|
}
|
|
|
|
],
|
|
|
|
'openSUSE:Factory:Staging:U': [],
|
2014-06-16 17:15:24 +02:00
|
|
|
'openSUSE:Factory:Staging:B': [],
|
|
|
|
'openSUSE:Factory:Staging:C': [
|
2014-06-23 14:08:00 +02:00
|
|
|
{
|
|
|
|
'who': 'Admin',
|
|
|
|
'when': '2014-06-01 17:56:28 UTC',
|
|
|
|
'id': '2',
|
|
|
|
'body': ("The list of requests tracked in openSUSE:Factory:Staging:C has changed:\n\n"
|
|
|
|
" * Request#501 for package apparmor submitted by Admin\n"
|
|
|
|
" * Request#502 for package mariadb submitted by Admin\n")
|
2014-06-16 17:15:24 +02:00
|
|
|
}
|
|
|
|
],
|
2014-06-24 14:11:06 +02:00
|
|
|
'openSUSE:Factory:Staging:J': [],
|
2014-06-04 16:54:21 +02:00
|
|
|
}
|
|
|
|
|
2015-02-26 15:19:29 +01:00
|
|
|
# To track comments created during test execution, even if
|
|
|
|
# they have been deleted afterward
|
2014-06-16 17:15:24 +02:00
|
|
|
self.comment_bodies = []
|
|
|
|
|
2015-02-26 15:19:29 +01:00
|
|
|
# Different spec files stored in some openSUSE:Factory
|
|
|
|
# projects
|
|
|
|
self.spec_list = {
|
|
|
|
'openSUSE:Factory/apparmor': [
|
|
|
|
{
|
|
|
|
'spec': 'apparmor.spec',
|
|
|
|
}
|
|
|
|
],
|
|
|
|
}
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
#
|
|
|
|
# /request/
|
|
|
|
#
|
|
|
|
|
|
|
|
@GET(re.compile(r'/request/\d+'))
|
|
|
|
def request(self, request, uri, headers):
|
|
|
|
"""Return a request XML description."""
|
|
|
|
request_id = re.search(r'(\d+)', uri).group(1)
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
template = string.Template(self._fixture(uri))
|
|
|
|
response = (200, headers, template.substitute(self.requests[request_id]))
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('REQUEST', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
def _request(self, request_id):
|
|
|
|
"""Utility function to recover a request from the ID."""
|
2018-11-17 10:01:41 +01:00
|
|
|
template = string.Template(self._fixture(urljoin(APIURL, '/request/' + request_id)))
|
2014-06-03 18:05:05 +02:00
|
|
|
return template.substitute(self.requests[request_id])
|
|
|
|
|
|
|
|
@POST(re.compile(r'/request/\d+'))
|
|
|
|
def review_request(self, request, uri, headers):
|
|
|
|
request_id = re.search(r'(\d+)', uri).group(1)
|
2018-11-17 10:01:41 +01:00
|
|
|
qs = parse_qs(urlparse(uri).query)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
|
|
|
|
# Adding review
|
|
|
|
if qs.get('cmd', None) == ['addreview']:
|
|
|
|
self.requests[request_id]['request'] = 'review'
|
|
|
|
self.requests[request_id]['review'] = 'new'
|
|
|
|
# Changing review
|
|
|
|
if qs.get('cmd', None) == ['changereviewstate']:
|
|
|
|
self.requests[request_id]['request'] = 'new'
|
|
|
|
self.requests[request_id]['review'] = qs['newstate'][0]
|
|
|
|
# Project review
|
|
|
|
if 'by_project' in qs:
|
|
|
|
self.requests[request_id]['by'] = 'project'
|
|
|
|
self.requests[request_id]['by_who'] = qs['by_project'][0]
|
|
|
|
# Group review
|
|
|
|
if 'by_group' in qs:
|
|
|
|
self.requests[request_id]['by'] = 'group'
|
|
|
|
self.requests[request_id]['by_who'] = qs[u'by_group'][0]
|
|
|
|
|
|
|
|
try:
|
|
|
|
response = (200, headers, self._request(request_id))
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('REVIEW REQUEST', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
@GET('/request')
|
|
|
|
def request_search(self, request, uri, headers):
|
|
|
|
"""Request search function."""
|
2018-11-17 10:01:41 +01:00
|
|
|
qs = parse_qs(urlparse(uri).query)
|
2014-06-03 18:05:05 +02:00
|
|
|
states = qs['states'][0].split(',')
|
|
|
|
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
|
|
|
|
requests = [rq for rq in self.requests.values() if rq['request'] in states]
|
|
|
|
if 'package' in qs:
|
|
|
|
requests = [rq for rq in requests if qs['package'][0] in rq['package']]
|
|
|
|
|
|
|
|
try:
|
|
|
|
_requests = '\n'.join(self._request(rq['id']) for rq in requests)
|
|
|
|
|
|
|
|
template = string.Template(self._fixture(uri, filename='result.xml'))
|
|
|
|
result = template.substitute(
|
|
|
|
{
|
|
|
|
'nrequests': len(requests),
|
|
|
|
'requests': _requests,
|
|
|
|
})
|
|
|
|
response = (200, headers, result)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('SEARCH REQUEST', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
#
|
|
|
|
# /source/
|
|
|
|
#
|
|
|
|
|
2018-06-15 08:41:24 +02:00
|
|
|
@GET(re.compile(r'/source/[\w:]+/_attribute/[\w:]+$'))
|
|
|
|
def source_attribute(self, request, uri, headers):
|
|
|
|
"""Return attribute."""
|
|
|
|
|
|
|
|
match = re.search(r'/source/([\w:]+)/_attribute/(\w+):(\w+)$', uri)
|
|
|
|
project = match.group(1)
|
|
|
|
ns = match.group(2)
|
|
|
|
name = match.group(3)
|
|
|
|
|
|
|
|
# never returns 404 - unless the project does not exist,
|
|
|
|
# which we can't (and don't need) to model
|
|
|
|
response = (200, headers, '<attributes/>')
|
|
|
|
print(self.attributes, project, ns, name)
|
|
|
|
if not project in self.attributes:
|
|
|
|
return response
|
|
|
|
hash = self.attributes[project]
|
|
|
|
|
|
|
|
if not ns in hash and not name in hash[ns]:
|
|
|
|
return response
|
|
|
|
|
|
|
|
root = ET.fromstring('<attributes><attribute name="" namespace="">' +
|
|
|
|
'<value/></attribute></attributes>')
|
|
|
|
root.find('./attribute').set('name', name)
|
|
|
|
root.find('./attribute').set('namespace', ns)
|
|
|
|
root.find('./attribute/value').text = hash[ns][name]
|
|
|
|
|
|
|
|
response = (200, headers, ET.tostring(root))
|
2017-05-01 17:10:36 -05:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('GET ATTRIBUTE', uri, response)
|
2017-05-01 17:10:36 -05:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2018-06-15 08:41:24 +02:00
|
|
|
@POST(re.compile(r'/source/[\w:]+/_attribute$'))
|
|
|
|
def source_attribute_post(self, request, uri, headers):
|
|
|
|
"""Set an attribute"""
|
|
|
|
project = re.search(r'/source/([\w:]+)/_attribute', uri).group(1)
|
|
|
|
_attrib = ET.fromstring(request.body).find('./attribute')
|
|
|
|
hash = self.attributes.setdefault(project, {})
|
|
|
|
hash = hash.setdefault(_attrib.get('namespace'), {})
|
|
|
|
text = _attrib.find('./value').text
|
|
|
|
hash[_attrib.get('name')] = text or ''
|
|
|
|
response = (200, headers, request.body)
|
2017-05-01 17:10:36 -05:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('PUT ATTRIBUTE', uri, response)
|
2017-05-01 17:10:36 -05:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2017-05-01 22:31:36 -05:00
|
|
|
@GET(re.compile(r'/source/openSUSE:Factory:Staging/dashboard/\w+'))
|
|
|
|
def source_staging_dashboard(self, request, uri, headers):
|
|
|
|
"""Return staging dashboard file."""
|
|
|
|
filename = re.search(r'/source/[\w:]+/\w+/(\w+)', uri).group(1)
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
contents = self.dashboard.get(filename, self._fixture(uri))
|
|
|
|
response = (200, headers, contents)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2017-05-01 22:31:36 -05:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('STAGING DASHBOARD FILE', uri, response)
|
2017-05-01 22:31:36 -05:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
@PUT(re.compile(r'/source/openSUSE:Factory:Staging/dashboard/\w+'))
|
|
|
|
def source_staging_dashboard_put(self, request, uri, headers):
|
|
|
|
"""Set the staging dashboard file contents."""
|
|
|
|
filename = re.search(r'/source/[\w:]+/\w+/(\w+)', uri).group(1)
|
|
|
|
self.dashboard[filename] = request.body
|
|
|
|
response = (200, headers, request.body)
|
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('PUT STAGING DASHBOARD FILE', uri, response)
|
2017-05-01 22:31:36 -05:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2017-06-01 10:04:52 +02:00
|
|
|
@GET(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|U|J]/_project/_history'))
|
|
|
|
def source_staging_project_meta_history(self, request, uri, headers):
|
|
|
|
"""Return the _meta information for a staging project."""
|
|
|
|
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
history = """
|
|
|
|
<revisionlist>
|
|
|
|
<revision rev="1" vrev="">
|
|
|
|
<srcmd5>af5d42d465d31da28c1ba31806adeed0</srcmd5>
|
|
|
|
<version></version>
|
|
|
|
<time>1495711367</time>
|
|
|
|
<user>staging-bot</user>
|
|
|
|
</revision>
|
|
|
|
</revisionlist>"""
|
|
|
|
response = (200, headers, history)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2017-06-01 10:04:52 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('STAGING PROJECT _history META', uri, response)
|
2017-06-01 10:04:52 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2018-07-05 20:43:07 +02:00
|
|
|
@GET(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|U|J]?/_project/_meta'))
|
2017-06-01 10:04:52 +02:00
|
|
|
def source_staging_project_meta_revisioned(self, request, uri, headers):
|
|
|
|
"""Return the _meta information for a staging project."""
|
|
|
|
|
|
|
|
uri = uri.replace('/_project', '')
|
|
|
|
key = re.search(r'openSUSE:Factory:Staging:(\w(?:/\w+)?)/_meta', uri).group(1)
|
|
|
|
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
if key not in self.meta:
|
|
|
|
template = string.Template(self._fixture(uri))
|
|
|
|
self.meta[key] = template.substitute(self.staging_project[key])
|
|
|
|
|
|
|
|
meta = self.meta[key]
|
|
|
|
# Simulate missing _meta revision missing puppet request.
|
2017-09-26 19:03:22 +08:00
|
|
|
meta = meta.replace('- {author: Admin, id: 321, package: puppet, type: submit}', '')
|
2017-06-01 10:04:52 +02:00
|
|
|
response = (200, headers, meta)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2017-06-01 10:04:52 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('STAGING PROJECT _project _meta', uri, response)
|
2017-06-01 10:04:52 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2014-06-24 14:11:06 +02:00
|
|
|
@GET(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|J]/_project'))
|
2014-06-03 18:05:05 +02:00
|
|
|
def source_staging_project_project(self, request, uri, headers):
|
|
|
|
"""Return the _project information for a staging project."""
|
|
|
|
# Load the proper fixture and adjust mtime according the
|
|
|
|
# current time.
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
template = string.Template(self._fixture(uri))
|
|
|
|
if 'Staging:A' in uri:
|
|
|
|
project = template.substitute({'mtime': int(time.time()) - 3600 * 24 * 356})
|
2014-03-07 13:58:33 +01:00
|
|
|
else:
|
2014-06-03 18:05:05 +02:00
|
|
|
project = template.substitute({'mtime': int(time.time()) - 100})
|
|
|
|
response = (200, headers, project)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('STAGING PROJECT _PROJECT', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2014-06-24 14:11:06 +02:00
|
|
|
@GET(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|U|J](/\w+)?/_meta'))
|
2014-06-03 18:05:05 +02:00
|
|
|
def source_staging_project_meta(self, request, uri, headers):
|
|
|
|
"""Return the _meta information for a staging project."""
|
|
|
|
key = re.search(r'openSUSE:Factory:Staging:(\w(?:/\w+)?)/_meta', uri).group(1)
|
|
|
|
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
if key not in self.meta:
|
|
|
|
template = string.Template(self._fixture(uri))
|
|
|
|
self.meta[key] = template.substitute(self.staging_project[key])
|
|
|
|
|
|
|
|
meta = self.meta[key]
|
|
|
|
response = (200, headers, meta)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('STAGING PROJECT [PACKAGE] _META', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2014-06-24 14:11:06 +02:00
|
|
|
@PUT(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|U|J](/\w+)?/_meta'))
|
2014-06-03 18:05:05 +02:00
|
|
|
def put_source_staging_project_meta(self, request, uri, headers):
|
|
|
|
"""Set the _meta information for a staging project."""
|
|
|
|
key = re.search(r'openSUSE:Factory:Staging:(\w(?:/\w+)?)/_meta', uri).group(1)
|
|
|
|
|
|
|
|
self.meta[key] = request.body
|
|
|
|
|
|
|
|
meta = self.meta[key]
|
|
|
|
response = (200, headers, meta)
|
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('PUT STAGING PROJECT [PACKAGE] _META', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
@GET(re.compile(r'/source/openSUSE:Factory:Staging:B/wine'))
|
|
|
|
def source_stating_project_wine(self, request, uri, headers):
|
|
|
|
"""Return wine package information. Is a link."""
|
|
|
|
package = re.search(r'/source/([\w:]+/\w+)', uri).group(1)
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
template = string.Template(self._fixture(uri))
|
|
|
|
response = (200, headers, template.substitute(self.links[package]))
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('SOURCE WINE', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2018-10-24 16:29:15 -05:00
|
|
|
@DELETE(re.compile(r'/source/openSUSE:Factory:Staging:[B|C]/\w+'))
|
2014-06-16 17:15:24 +02:00
|
|
|
def delete_package(self, request, uri, headers):
|
|
|
|
"""Delete a source package from a Staging project."""
|
|
|
|
package = re.search(r'/source/([\w:]+/\w+)', uri).group(1)
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
del self.links[package]
|
|
|
|
response = (200, headers, '<result>Ok</result>')
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-16 17:15:24 +02:00
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('DELETE', uri, response)
|
2014-06-16 17:15:24 +02:00
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
return response
|
|
|
|
|
2015-02-26 15:19:29 +01:00
|
|
|
@GET(re.compile(r'/source/openSUSE:Factory/apparmor$'))
|
|
|
|
def source_project_apparmor(self, request, uri, headers):
|
|
|
|
"""Return apparmor spec list."""
|
|
|
|
package = re.search(r'/source/([\w:]+/\w+)', uri).group(1)
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
template = string.Template(self._fixture(uri, filename='apparmor.xml'))
|
|
|
|
entry_template = string.Template(self._fixture(uri, filename='_entry.xml'))
|
|
|
|
entries = ''.join(entry_template.substitute(entry) for entry in self.spec_list[package])
|
|
|
|
response = (200, headers, template.substitute({'entries': entries}))
|
|
|
|
|
|
|
|
# The next call len() will be 2
|
|
|
|
if len(self.spec_list[package]) == 1:
|
|
|
|
self.spec_list[package].append({'spec': 'apparmor-doc.spec'})
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2015-02-26 15:19:29 +01:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('SOURCE APPARMOR', uri, response)
|
2015-02-26 15:19:29 +01:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2014-07-04 15:20:28 +02:00
|
|
|
@GET(re.compile(r'/source/home:Admin/\w+'))
|
2014-06-03 18:05:05 +02:00
|
|
|
def source_project(self, request, uri, headers):
|
|
|
|
"""Return information of a source package."""
|
2018-11-17 10:01:41 +01:00
|
|
|
qs = parse_qs(urlparse(uri).query)
|
2014-07-04 15:20:28 +02:00
|
|
|
index = re.search(r'/source/([\w:]+/\w+)', uri).group(1)
|
|
|
|
project, package = index.split('/')
|
2014-06-03 18:05:05 +02:00
|
|
|
response = (404, headers, '<result>Not found</result>')
|
2014-07-04 15:20:28 +02:00
|
|
|
|
|
|
|
suffix = '_expanded' if 'expanded' in qs else '_info' if 'info' in qs else ''
|
|
|
|
path = os.path.join('source', project, package + suffix)
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
try:
|
2014-07-04 15:20:28 +02:00
|
|
|
template = string.Template(self._fixture(path=path))
|
|
|
|
response = (200, headers, template.substitute(self.package[index]))
|
2014-06-03 18:05:05 +02:00
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('SOURCE HOME:ADMIN', package, uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2014-06-17 14:39:51 +02:00
|
|
|
@POST(re.compile(r'/source/openSUSE:Factory:Rings:1-MinimalX/\w+'))
|
|
|
|
def show_wine_link(self, request, uri, headers):
|
|
|
|
# TODO: only useful answer if cmd=showlinked
|
|
|
|
return (200, headers, '<collection/>')
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
@GET('/source/openSUSE:Factory:Staging:A/wine')
|
|
|
|
def source_link(self, request, uri, headers):
|
|
|
|
project_package = re.search(r'/source/([\w:]+/\w+)', uri).group(1)
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
template = string.Template(self._fixture(uri))
|
|
|
|
response = (200, headers, template.substitute(self.links[project_package]))
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('SOURCE HOME:ADMIN WINE', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2014-06-17 14:39:51 +02:00
|
|
|
@PUT(re.compile(r'/source/openSUSE:Factory:Staging:[AB]/\w+/_link'))
|
2014-06-03 18:05:05 +02:00
|
|
|
def put_source_link(self, request, uri, headers):
|
|
|
|
"""Create wine link in staging project A."""
|
|
|
|
project_package = re.search(r'/source/([\w:]+/\w+)/_link', uri).group(1)
|
|
|
|
project, package = re.search(r'([\w:]+)/(\w+)', project_package).groups()
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
_link = ET.fromstring(request.body)
|
|
|
|
self.links[project_package] = {
|
|
|
|
'prj': project,
|
|
|
|
'pkg': package,
|
|
|
|
'devprj': _link.get('project')
|
2014-03-05 16:22:14 +01:00
|
|
|
}
|
2014-06-03 18:05:05 +02:00
|
|
|
response = (200, headers, '<result>Ok</result>')
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('PUT SOURCE WINE _LINK', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
#
|
|
|
|
# /build/
|
|
|
|
#
|
|
|
|
|
2014-07-04 15:20:28 +02:00
|
|
|
# @GET(re.compile(r'build/home:Admin/_result'))
|
|
|
|
# def build_lastsuccess(self, request, uri, headers):
|
|
|
|
# package = re.search(r'/source/([\w:]+/\w+)', uri).group(1)
|
|
|
|
# response = (404, headers, '<result>Not found</result>')
|
|
|
|
# try:
|
|
|
|
# template = string.Template(self._fixture(uri))
|
|
|
|
# response = (200, headers, template.substitute(self.package[package]))
|
|
|
|
# except Exception as e:
|
|
|
|
# if DEBUG:
|
|
|
|
# print uri, e
|
|
|
|
|
|
|
|
# if DEBUG:
|
|
|
|
# print 'BUILD _RESULT LASTBUILDSUCCESS', package, uri, response
|
|
|
|
|
|
|
|
# return response
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
#
|
|
|
|
# /search/
|
|
|
|
#
|
|
|
|
|
2019-02-15 11:53:04 -06:00
|
|
|
@GET('/search/project')
|
|
|
|
def search_project(self, request, uri, headers):
|
|
|
|
return (200, headers, '<collection matches="0"></collection>')
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
@GET('/search/project/id')
|
|
|
|
def search_project_id(self, request, uri, headers):
|
|
|
|
"""Return a search result /search/project/id."""
|
2018-11-17 10:01:41 +01:00
|
|
|
assert urlparse(uri).query == urlencode(
|
2018-02-05 19:44:21 -06:00
|
|
|
{'match': 'starts-with(@name, "openSUSE:Factory:Staging:")'})
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
template = string.Template(self._fixture(uri, filename='result.xml'))
|
|
|
|
projects = '\n'.join(
|
|
|
|
'<project name="%s"/>' % staging['project'] for staging in self.staging_project.values()
|
|
|
|
)
|
|
|
|
result = template.substitute(
|
|
|
|
{
|
|
|
|
'nprojects': len(self.staging_project),
|
|
|
|
'projects': projects,
|
|
|
|
})
|
|
|
|
response = (200, headers, result)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('SEARCH PROJECT ID', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
@GET('/search/request')
|
|
|
|
def search_request(self, request, uri, headers):
|
|
|
|
"""Return a search result for /search/request."""
|
2018-11-17 10:01:41 +01:00
|
|
|
query = unquote(urlparse(uri).query)
|
2014-06-24 14:11:06 +02:00
|
|
|
assert query in (
|
2014-09-22 17:56:35 +02:00
|
|
|
"match=state/@name='review'+and+review[@by_group='factory-staging'+and+@state='new']+and+(target[@project='openSUSE:Factory']+or+target[@project='openSUSE:Factory:NonFree'])",
|
|
|
|
"match=state/@name='review'+and+review[@by_user='factory-repo-checker'+and+@state='new']+and+(target[@project='openSUSE:Factory']+or+target[@project='openSUSE:Factory:NonFree'])"
|
2014-06-24 14:11:06 +02:00
|
|
|
)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
|
2014-06-24 14:11:06 +02:00
|
|
|
by, by_who = re.search(r"@by_(user|group)='([-\w]+)'", query).groups()
|
|
|
|
state = re.search(r"@state='(\w+)'", query).group(1)
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
requests = [rq for rq in self.requests.values()
|
|
|
|
if rq['request'] == 'review'
|
2014-06-24 14:11:06 +02:00
|
|
|
and rq['review'] == state
|
|
|
|
and rq['by'] == by
|
|
|
|
and rq['by_who'] == by_who]
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
try:
|
|
|
|
_requests = '\n'.join(self._request(rq['id']) for rq in requests)
|
|
|
|
|
|
|
|
template = string.Template(self._fixture(uri, filename='result.xml'))
|
|
|
|
result = template.substitute(
|
|
|
|
{
|
|
|
|
'nrequests': len(requests),
|
|
|
|
'requests': _requests,
|
|
|
|
})
|
|
|
|
response = (200, headers, result)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('SEARCH REQUEST', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
@GET('/search/request/id')
|
|
|
|
def search_request_id(self, request, uri, headers):
|
|
|
|
"""Return a search result for /search/request/id."""
|
2018-11-17 10:01:41 +01:00
|
|
|
query = urlparse(uri).query
|
2014-06-03 18:05:05 +02:00
|
|
|
project = re.search(r"@by_project='([^']+)'", query).group(1)
|
|
|
|
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
|
|
|
|
requests = [rq for rq in self.requests.values()
|
|
|
|
if rq['request'] == 'review'
|
|
|
|
and rq['review'] == 'new'
|
|
|
|
and rq['by'] == 'project'
|
|
|
|
and rq['by_who'] == project]
|
|
|
|
|
|
|
|
try:
|
|
|
|
_requests = '\n'.join('<request id="%s"/>' % rq['id'] for rq in requests)
|
|
|
|
|
|
|
|
template = string.Template(self._fixture(uri, filename='result.xml'))
|
|
|
|
result = template.substitute(
|
|
|
|
{
|
|
|
|
'nrequests': len(requests),
|
|
|
|
'requests': _requests,
|
|
|
|
})
|
|
|
|
response = (200, headers, result)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('SEARCH REQUEST', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
#
|
|
|
|
# /comments/
|
|
|
|
#
|
|
|
|
|
2014-06-04 16:54:21 +02:00
|
|
|
@GET(re.compile(r'/comments/project/.*'))
|
|
|
|
def get_comment(self, request, uri, headers):
|
|
|
|
"""Get comments for a project."""
|
|
|
|
prj = re.search(r'comments/project/([^/]*)', uri).group(1)
|
|
|
|
comments = self.comments[prj]
|
|
|
|
if not comments:
|
|
|
|
return (200, headers, '<comments project="%s"/>' % prj)
|
|
|
|
else:
|
|
|
|
ret_str = '<comments project="%s">' % prj
|
|
|
|
for c in comments:
|
|
|
|
ret_str += '<comment who="%s" when="%s" id="%s">' % (c['who'], c['when'], c['id'])
|
2014-06-04 18:34:08 +02:00
|
|
|
ret_str += c['body'].replace('<', '<').replace('>', '>')
|
2014-06-04 16:54:21 +02:00
|
|
|
ret_str += '</comment>'
|
|
|
|
ret_str += '</comments>'
|
|
|
|
return (200, headers, ret_str)
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
@POST(re.compile(r'/comments/project/.*'))
|
2014-06-04 16:54:21 +02:00
|
|
|
def post_comment(self, request, uri, headers):
|
|
|
|
"""Add comment to a project."""
|
2017-06-01 10:04:52 +02:00
|
|
|
prj = re.search(r'comments/project/([^/?]*)', uri).group(1)
|
2014-06-23 14:08:00 +02:00
|
|
|
comment = {
|
|
|
|
'who': 'Admin',
|
|
|
|
'when': time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime()),
|
|
|
|
'id': str(sum(len(c) for c in self.comments.values()) + 1),
|
|
|
|
'body': request.body
|
|
|
|
}
|
2014-06-04 16:54:21 +02:00
|
|
|
self.comments[prj].append(comment)
|
2014-06-16 17:15:24 +02:00
|
|
|
self.comment_bodies.append(request.body)
|
2014-06-03 18:05:05 +02:00
|
|
|
response = (200, headers, '<result>Ok</result>')
|
|
|
|
return response
|
|
|
|
|
2014-06-04 16:54:21 +02:00
|
|
|
@DELETE(re.compile(r'/comment/\d+'))
|
|
|
|
def delete_comment(self, request, uri, headers):
|
|
|
|
"""Delete a comments."""
|
|
|
|
comment_id = re.search(r'comment/(\d+)', uri).group(1)
|
|
|
|
for prj in self.comments:
|
|
|
|
self.comments[prj] = [c for c in self.comments[prj] if c['id'] != comment_id]
|
|
|
|
return (200, headers, '<result>Ok</result>')
|
|
|
|
|
2014-09-12 15:00:14 +02:00
|
|
|
#
|
|
|
|
# /project/staging_projects
|
|
|
|
#
|
|
|
|
|
|
|
|
@GET(re.compile(r'/project/staging_projects/openSUSE:Factory.*'))
|
|
|
|
def staging_projects(self, request, uri, headers):
|
|
|
|
"""Return a JSON fixture."""
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
2018-11-17 10:01:41 +01:00
|
|
|
path = urlparse(uri).path + '.json'
|
2017-05-02 18:11:40 -05:00
|
|
|
template = string.Template(self._fixture(path=path))
|
|
|
|
response = (200, headers, template.substitute({
|
|
|
|
'update_at_too_recent': (datetime.utcnow() - timedelta(minutes=2)).isoformat(),
|
|
|
|
'declined_updated_at_under': (datetime.utcnow() - timedelta(days=1)).isoformat(),
|
|
|
|
'declined_updated_at_over': (datetime.utcnow() - timedelta(days=10)).isoformat(),
|
|
|
|
}))
|
2014-09-12 15:00:14 +02:00
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-09-12 15:00:14 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('REQUEST', uri, response)
|
2014-09-12 15:00:14 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
2014-06-03 18:05:05 +02:00
|
|
|
#
|
|
|
|
# Static fixtures
|
|
|
|
#
|
|
|
|
|
|
|
|
@GET(re.compile(r'.*'))
|
|
|
|
def default(self, request, uri, headers):
|
|
|
|
"""Default handler. Search in the fixture directory."""
|
|
|
|
response = (404, headers, '<result>Not found</result>')
|
|
|
|
try:
|
|
|
|
response = (200, headers, self._fixture(uri))
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print(uri, e)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
2018-06-15 08:41:24 +02:00
|
|
|
print('DEFAULT', uri, response)
|
2014-06-03 18:05:05 +02:00
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
def _fixture(self, uri=None, path=None, filename=None):
|
|
|
|
"""Read a file as a fixture."""
|
|
|
|
if not path:
|
2018-11-17 10:01:41 +01:00
|
|
|
path = urlparse(uri).path
|
2014-06-03 18:05:05 +02:00
|
|
|
path = path[1:] if path.startswith('/') else path
|
|
|
|
|
|
|
|
if filename:
|
|
|
|
fixture_path = os.path.join(self.fixtures, path, filename)
|
|
|
|
else:
|
|
|
|
fixture_path = os.path.join(self.fixtures, path)
|
|
|
|
|
|
|
|
with open(fixture_path) as f:
|
|
|
|
return f.read()
|