Completed
Push — master ( 889440...e965d2 )
by Dieter
01:16
created

is_repo_allowed()   D

Complexity

Conditions 8

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 8
dl 0
loc 32
rs 4
1
# vim: set expandtab sw=4 ts=4:
2
"""
3
Service related methods.
4
5
Copyright (C) 2014-2016 Dieter Adriaenssens <[email protected]>
6
7
This file is part of buildtimetrend/python-lib
8
<https://github.com/buildtimetrend/python-lib/>
9
10
This program is free software: you can redistribute it and/or modify
11
it under the terms of the GNU Affero General Public License as published by
12
the Free Software Foundation, either version 3 of the License, or
13
any later version.
14
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU Affero General Public License for more details.
19
20
You should have received a copy of the GNU Affero General Public License
21
along with this program. If not, see <http://www.gnu.org/licenses/>.
22
"""
23
24
from __future__ import division
25
import cgi
26
from buildtimetrend import logger
27
from buildtimetrend.settings import Settings
28
from buildtimetrend import keenio
29
from buildtimetrend.keenio import has_build_id
30
31
32
def is_repo_allowed(repo):
33
    """
34
    Check if repo is allowed.
35
36
    A repository name is checked against a list of denied and allowed repos.
37
    The 'denied_repo' check takes precendence over 'allowed_repo' check.
38
    The list of denied/allowed repos is defined with settings 'denied_repo'
39
    and 'allowed_repo'.
40
    If the settings are not defined,
41
    the repo is not checked against the denied/allowed lists.
42
    Both 'denied_repo' and 'allowed_repo' can have multiple values,
43
    if any of them matches a substring of the repo, the repo is denied/allowed.
44
45
    Parameters:
46
    -repo : repository name
47
    """
48
    if repo is None:
49
        logger.warning("Repo is not defined")
50
        return False
51
52
    denied_message = "Project '%s' is not allowed."
53
    denied_repo = Settings().get_setting("denied_repo")
54
    allowed_repo = Settings().get_setting("allowed_repo")
55
56
    if denied_repo is not None and \
57
            any(x in repo for x in denied_repo) or \
58
            allowed_repo is not None and \
59
            not any(x in repo for x in allowed_repo):
60
        logger.warning(denied_message, repo)
61
        return False
62
63
    return True
64
65
66
def get_repo_data_detail(repo):
67
    """
68
    Get level of data detail storage of a repo.
69
70
    A repository name is checked against a list of repository names.
71
    If a match is found, the corresponding data detail level is used.
72
    Else, the default global setting is returned.
73
74
    Parameters:
75
    -repo : repository name
76
    """
77
    settings = Settings()
78
79
    if repo is None:
80
        logger.warning("Repo is not defined")
81
    else:
82
        repo_settings = settings.get_setting("repo_data_detail")
83
        for repo_substring, setting in repo_settings.items():
84
            if repo_substring in repo:
85
                return setting
86
87
    # return default global data_detail setting
88
    return settings.get_setting("data_detail")
89
90
91
def format_duration(duration):
92
    """
93
    Format duration from seconds to hours, minutes and seconds.
94
95
    Parameters:
96
    - duration : duration in seconds
97
    """
98
    if not isinstance(duration, (float, int)) or duration < 0:
99
        return "unknown"
100
101
    # round duration
102
    duration = round(duration)
103
104
    seconds = int(duration % 60)
105
    duration = duration / 60
106
    format_string = "{:d}s".format(seconds)
107
108
    if duration >= 1:
109
        minutes = int(duration % 60)
110
        duration = duration / 60
111
        format_string = "{:d}m {:s}".format(minutes, format_string)
112
113
        if duration >= 1:
114
            hours = int(duration % 60)
115
            format_string = "{:d}h {:s}".format(hours, format_string)
116
117
    return format_string
118
119
120
def check_process_parameters(repo=None, build=None):
121
    """
122
    Process setup parameters.
123
124
    Deprecated : functionality is split into
125
    validate_travis_request() and validate_task_parameters()
126
127
    Check parameters (repo and build)
128
    Returns error message, None when all parameters are fine
129
    """
130
    ret_val = validate_travis_request(repo, build)
131
    if ret_val is not None:
132
        return ret_val
133
    return validate_task_parameters(repo, build)
134
135
136
def validate_travis_request(repo=None, build=None):
137
    """
138
    Validate repo and build parameters of travis web request.
139
140
    Check parameters (repo and build)
141
    Returns error message, None when all parameters are fine.
142
    """
143
    if repo is None or build is None:
144
        logger.warning("Repo or build number are not set")
145
        return "Repo or build are not set, format : " \
146
            "/travis/<repo_owner>/<repo_name>/<build>"
147
148
    # check if repo is allowed
149
    if not is_repo_allowed(repo):
150
        return "Project '{}' is not allowed.".format(cgi.escape(repo))
151
152
    return None
153
154
155
def validate_task_parameters(repo=None, build=None):
156
    """
157
    Validate repo and build parameters of process_travis_buildlog().
158
159
    Check parameters (repo and build)
160
    Returns error message, None when all parameters are fine.
161
    """
162
    if not keenio.is_writable():
163
        return "Keen IO write key not set, no data was sent"
164
165
    try:
166
        if has_build_id(repo, build):
167
            template = "Build #{build} of project {repo} " \
168
                "already exists in database"
169
            return template.format(
170
                build=cgi.escape(str(build)), repo=cgi.escape(str(repo))
171
            )
172
    except Exception as msg:
173
        # Raise last exception again
174
        logger.error("Error checking if build exists : %s", msg)
175
        raise SystemError("Error checking if build exists.")
176
177
    return None
178