~joetalbott/uci-engine/user_auth

« back to all changes in this revision

Viewing changes to nf-stats-service/nfss/api/v1.py

  • Committer: Thomi Richards
  • Date: 2014-06-27 20:02:44 UTC
  • mto: (629.2.9 nfss)
  • mto: This revision was merged to the branch mainline in revision 636.
  • Revision ID: thomi.richards@canonical.com-20140627200244-zi7dwxnyw38ypr2f
Initial version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Ubuntu CI Engine
 
2
# Copyright 2014 Canonical Ltd.
 
3
 
 
4
# This program is free software: you can redistribute it and/or modify it
 
5
# under the terms of the GNU Affero General Public License version 3, as
 
6
# published by the Free Software Foundation.
 
7
 
 
8
# This program is distributed in the hope that it will be useful, but
 
9
# WITHOUT ANY WARRANTY; without even the implied warranties of
 
10
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
11
# PURPOSE.  See the GNU Affero General Public License for more details.
 
12
 
 
13
# You should have received a copy of the GNU Affero General Public License
 
14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 
 
16
"""V1 of the REST API.
 
17
 
 
18
This file contains the views for the v1 API, as well as the URL routing table
 
19
for the v1 API.
 
20
 
 
21
"""
 
22
from datetime import (
 
23
    datetime,
 
24
    timedelta,
 
25
    timezone,
 
26
)
 
27
import json
 
28
from pyramid.view import view_config
 
29
from pyramid.httpexceptions import HTTPBadRequest
 
30
 
 
31
from nfss import database
 
32
from nfss.auth import oauth_protected
 
33
 
 
34
 
 
35
UTC = timezone(timedelta(0))
 
36
 
 
37
 
 
38
def configure_routes(config):
 
39
    """Add url routes to 'config' object."""
 
40
    config.add_route('v1.root', '/')
 
41
    config.add_route('v1.project', '/{project}')
 
42
    config.add_route('v1.test', '/{project}/{test}')
 
43
 
 
44
 
 
45
@view_config(route_name='v1.root', renderer='json', request_method='GET')
 
46
def root(request):
 
47
    """Return summary data about the projects and tests."""
 
48
    data = database.get_details_for_all_projects(request.database())
 
49
    return dict(
 
50
        projects={
 
51
            r[0]: {
 
52
                'tests': json.loads(r[1]),
 
53
                'last_updated': r[2].isoformat(),
 
54
                'path': request.route_path('v1.project', project=r[0])
 
55
            } for r in data},
 
56
    )
 
57
 
 
58
 
 
59
@view_config(route_name='v1.project', renderer='json', request_method='GET')
 
60
def project(request):
 
61
    """Return detailed information about this project's tests."""
 
62
    project_name = request.matchdict['project']
 
63
    project_data = database.get_details_for_project(
 
64
        request.database(),
 
65
        project_name
 
66
    )
 
67
 
 
68
    for test in project_data:
 
69
        project_data[test]['path'] = request.route_path(
 
70
            'v1.test',
 
71
            project=project_name,
 
72
            test=test
 
73
        )
 
74
    return dict(project_name=project_name, tests=project_data)
 
75
 
 
76
 
 
77
@view_config(route_name='v1.test', renderer='json', request_method='GET')
 
78
def test(request):
 
79
    """Return data points for this particular test.
 
80
 
 
81
    Check the Range HTTP header, or return the last 30 days worth of data if
 
82
    it's not present.
 
83
 
 
84
    """
 
85
    # import pudb; pudb.set_trace()
 
86
    project_name = request.matchdict['project']
 
87
    test_name = request.matchdict['test']
 
88
    start = try_parse_date(request.params.get('start_date', None))
 
89
    end = try_parse_date(request.params.get('end_date', None))
 
90
    data, f, l, df, dl = database.get_details_for_test(
 
91
        request.database(),
 
92
        project_name,
 
93
        test_name,
 
94
        start,
 
95
        end,
 
96
    )
 
97
    return dict(
 
98
        project_name=project_name,
 
99
        test_name=test_name,
 
100
        first_data=f.isoformat(),
 
101
        last_data=l.isoformat(),
 
102
        data_range_first=df.isoformat(),
 
103
        data_range_last=dl.isoformat(),
 
104
        data=json.loads(data) if data else [],
 
105
    )
 
106
 
 
107
 
 
108
def try_parse_date(date_param):
 
109
    if date_param is not None:
 
110
        try:
 
111
            return datetime.fromtimestamp(float(date_param), UTC)
 
112
        except:
 
113
            return None
 
114
    return None
 
115
 
 
116
 
 
117
@view_config(route_name='v1.test', renderer='json', request_method='POST')
 
118
@oauth_protected()
 
119
def test_add(request, oauth_request):
 
120
    """Add data points to this test.
 
121
 
 
122
    Return the created id of the data point added to the DB if it was
 
123
    successful, or an error if it wasn't.
 
124
 
 
125
    TODO: Secure this method somehow. Oauth2 token?
 
126
    """
 
127
    try:
 
128
        project_name = request.matchdict['project']
 
129
        test_name = request.matchdict['test']
 
130
        data = request.params['data']
 
131
    except KeyError as e:
 
132
        raise HTTPBadRequest("Missing data in POST request: %s" % e)
 
133
    else:
 
134
        created_id = database.insert_test_data(
 
135
            request.database(),
 
136
            project_name,
 
137
            test_name,
 
138
            data,
 
139
            oauth_request.client_key
 
140
        )
 
141
        return dict(created_id=created_id)