Skip to content

Commit dfbb7d5

Browse files
author
Vladimir Kotal
authored
sync.py needs to use RESTful API calls (#2199)
1 parent 927782e commit dfbb7d5

File tree

4 files changed

+128
-46
lines changed

4 files changed

+128
-46
lines changed

tools/sync/commands.py

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import os
2626
import command
2727
from command import Command
28+
from opengrok import put, post, delete
29+
from utils import is_web_uri
30+
import json
2831

2932

3033
class CommandsBase:
@@ -67,50 +70,88 @@ def __init__(self, base):
6770
self.logger = logging.getLogger(__name__)
6871
logging.basicConfig()
6972

73+
def run_command(self, command):
74+
cmd = Command(command,
75+
args_subst={"PROJECT": self.name},
76+
args_append=[self.name], excl_subst=True)
77+
cmd.execute()
78+
self.retcodes[str(cmd)] = cmd.getretcode()
79+
self.outputs[str(cmd)] = cmd.getoutput()
80+
81+
def call_rest_api(self, command):
82+
"""
83+
Make RESTful API call.
84+
"""
85+
PROJECT_SUBST = '%PROJECT%'
86+
87+
uri = command[0].replace(PROJECT_SUBST, self.name)
88+
verb = command[1]
89+
data = command[2]
90+
91+
if len(data) > 0:
92+
headers = {'Content-Type': 'application/json'}
93+
json_data = json.dumps(data).replace(PROJECT_SUBST, self.name)
94+
self.logger.debug("JSON data: {}".format(json_data))
95+
96+
if verb == 'PUT':
97+
put(self.logger, uri, headers=headers, data=json_data)
98+
elif verb == 'POST':
99+
post(self.logger, uri, headers=headers, data=json_data)
100+
elif verb == 'DELETE':
101+
delete(self.logger, uri, data)
102+
else:
103+
self.logger.error('Unknown verb in command {}'.
104+
format(command))
105+
70106
def run(self):
71107
"""
72108
Run the sequence of commands and capture their output and return code.
73109
First command that returns code other than 0 terminates the sequence.
74110
If the command has return code 2, the sequence will be terminated
75111
however it will not be treated as error.
112+
113+
Any command entry that is a URI, will be used to submit RESTful API
114+
request. Return codes for these requests are not checked.
76115
"""
77116

78117
for command in self.commands:
79-
cmd = Command(command,
80-
args_subst={"ARG": self.name},
81-
args_append=[self.name], excl_subst=True)
82-
cmd.execute()
83-
self.retcodes[str(cmd)] = cmd.getretcode()
84-
self.outputs[str(cmd)] = cmd.getoutput()
85-
86-
# If a command fails, terminate the sequence of commands.
87-
retcode = cmd.getretcode()
88-
if retcode != 0:
89-
if retcode == 2:
90-
self.logger.info("command '{}' requested break".
91-
format(cmd))
92-
self.run_cleanup()
93-
else:
94-
self.logger.info("command '{}' failed with code {}, "
95-
"breaking".format(cmd, retcode))
96-
self.failed = True
97-
self.run_cleanup()
98-
break
118+
if is_web_uri(command[0]):
119+
self.call_rest_api(command)
120+
else:
121+
self.run_command(command)
122+
123+
# If a command fails, terminate the sequence of commands.
124+
retcode = cmd.getretcode()
125+
if retcode != 0:
126+
if retcode == 2:
127+
self.logger.info("command '{}' requested break".
128+
format(cmd))
129+
self.run_cleanup()
130+
else:
131+
self.logger.info("command '{}' failed with code {}, "
132+
"breaking".format(cmd, retcode))
133+
self.failed = True
134+
self.run_cleanup()
135+
break
99136

100137
def run_cleanup(self):
101138
"""
102139
Call cleanup in case the sequence failed or termination was requested.
103140
"""
104141
if self.cleanup:
105-
self.logger.debug("Running cleanup command '{}'".
106-
format(self.cleanup))
107-
cmd = Command(self.cleanup,
108-
args_subst={"ARG": self.name},
109-
args_append=[self.name], excl_subst=True)
110-
cmd.execute()
111-
if cmd.getretcode() != 0:
112-
self.logger.info("cleanup command '{}' failed with code {}".
113-
format(self.cleanup, cmd.getretcode()))
142+
if is_web_uri(self.cleanup[0]):
143+
self.call_rest_api(self.cleanup)
144+
else:
145+
self.logger.debug("Running cleanup command '{}'".
146+
format(self.cleanup))
147+
cmd = Command(self.cleanup,
148+
args_subst={"ARG": self.name},
149+
args_append=[self.name], excl_subst=True)
150+
cmd.execute()
151+
if cmd.getretcode() != 0:
152+
self.logger.info("cleanup command '{}' failed with "
153+
"code {}".
154+
format(self.cleanup, cmd.getretcode()))
114155

115156
def check(self, ignore_errors):
116157
"""

tools/sync/opengrok.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,50 @@
2525
import requests
2626
import urllib.parse
2727
import traceback
28+
from urllib.parse import urlparse
2829

2930

30-
def get(logger, uri, params=None):
31+
def get(logger, uri, params=None, headers=None):
3132
try:
32-
return requests.get(uri, params=params)
33+
proxies = get_proxies(uri)
34+
return requests.get(uri, params=params, proxies=proxies)
3335
except Exception as e:
3436
logger.debug(traceback.format_exc())
3537
return None
3638

3739

38-
def delete(logger, uri, params=None):
40+
def delete(logger, uri, params=None, headers=None):
3941
try:
40-
return requests.delete(uri, params=params)
42+
proxies = get_proxies(uri)
43+
return requests.delete(uri, params=params, proxies=proxies)
4144
except Exception as e:
4245
logger.debug(traceback.format_exc())
4346
return None
4447

4548

46-
def post(logger, uri, data=None):
49+
def post(logger, uri, headers=None, data=None):
50+
rv = None
4751
try:
48-
return requests.post(uri, data=data)
52+
proxies = get_proxies(uri)
53+
rv = requests.post(uri, data=data, headers=headers, proxies=proxies)
4954
except Exception as e:
5055
logger.debug(traceback.format_exc())
5156
return None
5257

58+
return rv
5359

54-
def put(logger, uri, data=None):
60+
61+
def put(logger, uri, headers=None, data=None):
62+
rv = None
5563
try:
56-
return requests.put(uri, data=data)
64+
proxies = get_proxies(uri)
65+
rv = requests.put(uri, data=data, headers=headers, proxies=proxies)
5766
except Exception as e:
5867
logger.debug(traceback.format_exc())
5968
return None
6069

70+
return rv
71+
6172

6273
def get_repos(logger, project, uri):
6374
"""
@@ -168,3 +179,22 @@ def delete_project(logger, project, uri):
168179

169180
def get_uri(*uri_parts):
170181
return '/'.join(s.strip('/') for s in uri_parts)
182+
183+
184+
def is_localhost_url(url):
185+
"""
186+
Check if given URL is based on localhost.
187+
"""
188+
189+
o = urlparse(url)
190+
return o.hostname in ['localhost', '127.0.0.1', '::1']
191+
192+
193+
def get_proxies(url):
194+
"""
195+
For localhost based requests it is undesirable to use proxies.
196+
"""
197+
if is_localhost_url(url):
198+
return {'http': None, 'https': None}
199+
else:
200+
return None

tools/sync/sync.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,23 +173,25 @@ def worker(base):
173173

174174
logger.debug("to process: {}".format(dirs_to_process))
175175

176-
projects = []
176+
cmds_base = []
177177
for d in dirs_to_process:
178-
proj = CommandsBase(d, config.get("commands"),
179-
config.get("cleanup"))
180-
projects.append(proj)
178+
cmd_base = CommandsBase(d, config.get("commands"),
179+
config.get("cleanup"))
180+
cmds_base.append(cmd_base)
181181

182+
# Map the commands into pool of workers so they can be processed.
182183
try:
183-
projects = pool.map(worker, projects, 1)
184+
cmds_base_results = pool.map(worker, cmds_base, 1)
184185
except KeyboardInterrupt:
185186
# XXX lock.release() or return 1 ?
186187
sys.exit(1)
187188
else:
188-
for proj in projects:
189+
for cmds_base in cmds_base_results:
189190
logger.debug("Checking results of project {}".
190-
format(proj))
191-
cmds = Commands(proj)
192-
cmds.fill(proj.retcodes, proj.outputs, proj.failed)
191+
format(cmds_base))
192+
cmds = Commands(cmds_base)
193+
cmds.fill(cmds_base.retcodes, cmds_base.outputs,
194+
cmds_base.failed)
193195
cmds.check(ignore_errors)
194196
except Timeout:
195197
logger.warning("Already running, exiting.")

tools/sync/utils.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from shutil import which
2626
import logging
2727
import sys
28+
from urllib.parse import urlparse
2829

2930

3031
def is_exe(fpath):
@@ -95,3 +96,11 @@ def diff_list(first, second):
9596
"""
9697
second = set(second)
9798
return [item for item in first if item not in second]
99+
100+
101+
def is_web_uri(url):
102+
"""
103+
Check if given string is web URL.
104+
"""
105+
o = urlparse(url)
106+
return o.scheme in ['http', 'https']

0 commit comments

Comments
 (0)