Skip to content

Commit 2b1cb72

Browse files
author
Glenn Jones
authored
Merge pull request #18 from Pilifer/master
Helper script to delete log files
2 parents f0f851e + adabb47 commit 2b1cb72

File tree

4 files changed

+118
-2
lines changed

4 files changed

+118
-2
lines changed

pythonanywhere/api.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,34 @@ def delete_log(self, log_type, index=0):
214214
response_text=response.text,
215215
)
216216
)
217+
218+
def get_log_info(self):
219+
url = get_api_endpoint().format(username=getpass.getuser(),
220+
flavor="files") + "tree/?path=/var/log/"
221+
response = call_api(url, "get")
222+
if not response.ok:
223+
raise Exception(
224+
"GET log files info via API failed, got {response}:{response_text}".format(
225+
response=response,
226+
response_text=response.text,
227+
)
228+
)
229+
file_list = response.json()
230+
log_types = ["access", "error", "server"]
231+
logs = {"access": [], "error": [], "server": []}
232+
log_prefix = "/var/log/{domain}.".format(domain=self.domain)
233+
for file_name in file_list:
234+
if type(file_name) == str and file_name.startswith(log_prefix):
235+
log = file_name[len(log_prefix):].split(".")
236+
if log[0] in log_types:
237+
log_type = log[0]
238+
if log[-1] == "log":
239+
log_index = 0
240+
elif log[-1] == "1":
241+
log_index = 1
242+
elif log[-1] == "gz":
243+
log_index = int(log[-2])
244+
else:
245+
continue
246+
logs[log_type].append(log_index)
247+
return logs

scripts/pa_autoconfigure_django.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
1313
Options:
1414
--domain=<domain> Domain name, eg www.mydomain.com [default: your-username.pythonanywhere.com]
15-
--python=<python-version> Python version, eg "2.7" [default: 3.6]
15+
--python=<python-version> Python version, eg "2.7" [default: 3.5]
1616
--nuke *Irrevocably* delete any existing web app config on this domain. Irrevocably.
1717
"""
1818

scripts/pa_delete_webapp_logs.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/python3.5
2+
"""Deletes webapp logs.
3+
4+
- gets list of logs via api
5+
- deletes logs via api
6+
7+
Usage:
8+
pa_delete_webapp_logs.py [--domain=<domain>] [--log_type=<log_type>] [--log_index=<log_index>]
9+
10+
Options:
11+
--domain=<domain> Domain name, eg www.mydomain.com [default: your-username.pythonanywhere.com]
12+
--log_type=<log_type> Log type, could be access, error, server or all [default: all]
13+
--log_index=<log_index> Log index, 0 for current log, 1-9 for one of archive logs or all [default: all]
14+
"""
15+
16+
from docopt import docopt
17+
import getpass
18+
import os
19+
20+
from pythonanywhere.api import Webapp
21+
from pythonanywhere.snakesay import snakesay
22+
23+
24+
def main(domain, log_type, log_index):
25+
if domain == 'your-username.pythonanywhere.com':
26+
username = getpass.getuser().lower()
27+
pa_domain = os.environ.get('PYTHONANYWHERE_DOMAIN', 'pythonanywhere.com')
28+
domain = '{username}.{pa_domain}'.format(username=username, pa_domain=pa_domain)
29+
30+
webapp = Webapp(domain)
31+
log_types = ["access", "error", "server"]
32+
logs = webapp.get_log_info()
33+
if log_type == "all" and log_index == "all":
34+
for key in log_types:
35+
for log in logs[key]:
36+
webapp.delete_log(key, log)
37+
elif log_type == "all":
38+
for key in log_types:
39+
webapp.delete_log(key, int(log_index))
40+
elif log_index == "all":
41+
for i in logs[log_type]:
42+
webapp.delete_log(log_type, int(i))
43+
else:
44+
webapp.delete_log(log_type, int(log_index))
45+
print(snakesay('All Done!'))
46+
47+
48+
if __name__ == '__main__':
49+
arguments = docopt(__doc__)
50+
main(arguments['--domain'], arguments['--log_type'], arguments['--log_index'])

tests/test_api.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ def test_delete_old_access_log(self, api_responses, api_token):
356356
assert post.request.body is None
357357
assert post.request.headers['Authorization'] == 'Token {api_token}'.format(api_token=api_token)
358358

359-
def test_raises_if_post_does_not_20x(self, api_responses, api_token):
359+
def test_raises_if_delete_does_not_20x(self, api_responses, api_token):
360360
expected_url = get_api_endpoint().format(
361361
username=getpass.getuser(), flavor="files") + "path/var/log/mydomain.com.access.log/"
362362
api_responses.add(responses.DELETE, expected_url, status=404, body="nope")
@@ -366,3 +366,38 @@ def test_raises_if_post_does_not_20x(self, api_responses, api_token):
366366

367367
assert "DELETE log file via API failed" in str(e.value)
368368
assert "nope" in str(e.value)
369+
370+
371+
class TestGetWebappLogs:
372+
373+
def test_get_list_of_logs(self, api_responses, api_token):
374+
expected_url = get_api_endpoint().format(
375+
username=getpass.getuser(), flavor="files") + "tree/?path=/var/log/"
376+
api_responses.add(responses.GET, expected_url, status=200,
377+
body="['/var/log/blah','/var/log/mydomain.com.access.log',\
378+
'/var/log/mydomain.com.access.log.1',\
379+
'/var/log/mydomain.com.access.log.2.gz',\
380+
'/var/log/mydomain.com.error.log',\
381+
'/var/log/mydomain.com.error.log.1',\
382+
'/var/log/mydomain.com.error.log.2.gz',\
383+
'/var/log/mydomain.com.server.log',\
384+
'/var/log/mydomain.com.server.log.1',\
385+
'/var/log/mydomain.com.server.log.2.gz']")
386+
387+
logs = Webapp("mydomain.com").get_log_info()
388+
389+
post = api_responses.calls[0]
390+
assert post.request.url == expected_url
391+
assert post.request.headers['Authorization'] == 'Token {api_token}'.format(api_token=api_token)
392+
assert logs == {"access": [0, 1, 2], "error": [0, 1, 2], "server": [0, 1, 2]}
393+
394+
def test_raises_if_get_does_not_20x(self, api_responses, api_token):
395+
expected_url = get_api_endpoint().format(
396+
username=getpass.getuser(), flavor="files") + "tree/?path=/var/log/"
397+
api_responses.add(responses.GET, expected_url, status=404, body="nope")
398+
399+
with pytest.raises(Exception) as e:
400+
Webapp("mydomain.com").get_log_info()
401+
402+
assert "GET log files info via API failed" in str(e.value)
403+
assert "nope" in str(e.value)

0 commit comments

Comments
 (0)