Skip to content

Commit f1835fd

Browse files
author
Vladimir Kotal
committed
add port and REST endpoint to trigger reindex
fixes #3535
1 parent c2de41a commit f1835fd

File tree

3 files changed

+106
-45
lines changed

3 files changed

+106
-45
lines changed

Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ RUN mkdir -p /opengrok /opengrok/etc /opengrok/data /opengrok/src && \
5555

5656
RUN python3 -m pip install /opengrok/tools/opengrok-tools*
5757

58+
# for /reindex REST endpoint handled by start.py
59+
RUN python3 -m pip install Flask Flask-HTTPAuth waitress
60+
5861
# environment variables
5962
ENV SRC_ROOT /opengrok/src
6063
ENV DATA_ROOT /opengrok/data

docker/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ The volume mounted to `/opengrok/src` should contain the projects you want to ma
8181
`URL_ROOT` | `/` | Override the sub-URL that OpenGrok should run on.
8282
`WORKERS` | number of CPUs in the container | number of workers to use for syncing (applies only to setup with projects enabled)
8383
`AVOID_PROJECTS` | empty | run in project less configuration. Set to non empty value disables projects.
84+
`REST_PORT` | 5000 | TCP port where simple REST app listens for GET requests on `/reindex` to trigger manual reindex.
85+
`REST_TOKEN` | None | if set, the REST app will require this token as Bearer token in order to trigger reindex.
8486

8587
To specify environment variable for `docker run`, use the `-e` option, e.g. `-e SYNC_PERIOD_MINUTES=30`
8688

docker/start.py

Lines changed: 101 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import time
3131
from pathlib import Path
3232
from requests import get, ConnectionError
33+
from flask import Flask
34+
from flask_httpauth import HTTPTokenAuth
35+
from waitress import serve
3336

3437
from opengrok_tools.utils.log import get_console_logger, \
3538
get_log_level, get_class_basename
@@ -62,6 +65,36 @@
6265
OPENGROK_WEBAPPS_DIR = os.path.join(tomcat_root, "webapps")
6366
OPENGROK_JAR = os.path.join(OPENGROK_LIB_DIR, 'opengrok.jar')
6467

68+
expected_token = None
69+
70+
sleep_event = threading.Event()
71+
app = Flask(__name__)
72+
auth = HTTPTokenAuth(scheme='Bearer')
73+
74+
75+
@auth.verify_token
76+
def verify_token(token):
77+
if expected_token is None:
78+
return "yes"
79+
80+
if token is not None and token == expected_token:
81+
return "yes"
82+
83+
84+
@app.route('/reindex')
85+
@auth.login_required
86+
def index():
87+
# Signal the sync/indexer thread.
88+
sleep_event.set()
89+
sleep_event.clear()
90+
91+
return "Reindex triggered"
92+
93+
94+
def rest_function(logger, rest_port):
95+
logger.info("Starting REST app on port {}".format(rest_port))
96+
serve(app, host="0.0.0.0", port=rest_port)
97+
6598

6699
def set_url_root(logger, url_root):
67100
"""
@@ -230,7 +263,14 @@ def indexer_no_projects(logger, uri, config_path, sync_period,
230263

231264
wait_for_tomcat(logger, uri)
232265

266+
periodic_sync = True
267+
if sync_period is None or sync_period == 0:
268+
periodic_sync = False
269+
233270
while True:
271+
if not periodic_sync:
272+
sleep_event.wait()
273+
234274
indexer_options = ['-s', OPENGROK_SRC_ROOT,
235275
'-d', OPENGROK_DATA_ROOT,
236276
'-c', '/usr/local/bin/ctags',
@@ -246,9 +286,10 @@ def indexer_no_projects(logger, uri, config_path, sync_period,
246286
jar=OPENGROK_JAR, doprint=True)
247287
indexer.execute()
248288

249-
sleep_seconds = sync_period * 60
250-
logger.info("Sleeping for {} seconds".format(sleep_seconds))
251-
time.sleep(sleep_seconds)
289+
if periodic_sync:
290+
sleep_seconds = sync_period * 60
291+
logger.info("Sleeping for {} seconds".format(sleep_seconds))
292+
time.sleep(sleep_seconds)
252293

253294

254295
def project_syncer(logger, loglevel, uri, config_path, sync_period,
@@ -262,7 +303,14 @@ def project_syncer(logger, loglevel, uri, config_path, sync_period,
262303

263304
set_config_value(logger, 'projectsEnabled', 'true', uri)
264305

306+
periodic_sync = True
307+
if sync_period is None or sync_period == 0:
308+
periodic_sync = False
309+
265310
while True:
311+
if not periodic_sync:
312+
sleep_event.wait()
313+
266314
refresh_projects(logger, uri)
267315

268316
if os.environ.get('OPENGROK_SYNC_YML'): # debug only
@@ -298,9 +346,10 @@ def project_syncer(logger, loglevel, uri, config_path, sync_period,
298346

299347
save_config(logger, uri, config_path)
300348

301-
sleep_seconds = sync_period * 60
302-
logger.info("Sleeping for {} seconds".format(sleep_seconds))
303-
time.sleep(sleep_seconds)
349+
if periodic_sync:
350+
sleep_seconds = sync_period * 60
351+
logger.info("Sleeping for {} seconds".format(sleep_seconds))
352+
time.sleep(sleep_seconds)
304353

305354

306355
def create_bare_config(logger, extra_indexer_options=None):
@@ -333,6 +382,21 @@ def create_bare_config(logger, extra_indexer_options=None):
333382
raise Exception("Failed to create bare configuration")
334383

335384

385+
def get_num_from_env(logger, env_name, default_value):
386+
value = default_value
387+
env_str = os.environ.get(env_name)
388+
if env_str:
389+
try:
390+
n = int(env_str)
391+
if n >= 0:
392+
value = n
393+
except ValueError:
394+
logger.error("{} is not a number: {}".
395+
format(env_name, env_str))
396+
397+
return value
398+
399+
336400
def main():
337401
log_level = os.environ.get('OPENGROK_LOG_LEVEL')
338402
if log_level:
@@ -347,17 +411,7 @@ def main():
347411
logger.debug("URI = {}".format(uri))
348412

349413
# default period for syncing (in minutes)
350-
sync_period = 10
351-
sync_env = os.environ.get('SYNC_TIME_MINUTES')
352-
if sync_env:
353-
try:
354-
n = int(sync_env)
355-
if n >= 0:
356-
sync_period = n
357-
except ValueError:
358-
logger.error("SYNC_TIME_MINUTES is not a number: {}".
359-
format(sync_env))
360-
414+
sync_period = get_num_from_env(logger, 'SYNC_TIME_MINUTES', 10)
361415
if sync_period == 0:
362416
logger.info("synchronization disabled")
363417
else:
@@ -390,34 +444,36 @@ def main():
390444
os.path.getsize(OPENGROK_CONFIG_FILE) == 0:
391445
create_bare_config(logger, extra_indexer_options.split())
392446

393-
if sync_period > 0:
394-
if use_projects:
395-
num_workers = multiprocessing.cpu_count()
396-
workers_env = os.environ.get('WORKERS')
397-
if workers_env:
398-
try:
399-
n = int(workers_env)
400-
if n > 0:
401-
num_workers = n
402-
except ValueError:
403-
logger.error("WORKERS is not a number: {}".
404-
format(workers_env))
405-
406-
logger.info('Number of sync workers: {}'.format(num_workers))
407-
408-
worker_function = project_syncer
409-
syncer_args = (logger, log_level, uri,
410-
OPENGROK_CONFIG_FILE,
411-
sync_period, num_workers, env)
412-
else:
413-
worker_function = indexer_no_projects
414-
syncer_args = (logger, uri, OPENGROK_CONFIG_FILE, sync_period,
415-
extra_indexer_options)
416-
417-
logger.debug("Starting sync thread")
418-
thread = threading.Thread(target=worker_function, name="Sync thread",
419-
args=syncer_args)
420-
thread.start()
447+
if use_projects:
448+
num_workers = get_num_from_env(logger, 'WORKERS',
449+
multiprocessing.cpu_count())
450+
logger.info('Number of sync workers: {}'.format(num_workers))
451+
452+
worker_function = project_syncer
453+
syncer_args = (logger, log_level, uri,
454+
OPENGROK_CONFIG_FILE,
455+
sync_period, num_workers, env)
456+
else:
457+
worker_function = indexer_no_projects
458+
syncer_args = (logger, uri, OPENGROK_CONFIG_FILE, sync_period,
459+
extra_indexer_options)
460+
461+
logger.debug("Starting sync thread")
462+
thread = threading.Thread(target=worker_function, name="Sync thread",
463+
args=syncer_args)
464+
thread.start()
465+
466+
rest_port = get_num_from_env(logger, 'REST_PORT', 5000)
467+
token = os.environ.get('REST_TOKEN')
468+
global expected_token
469+
if token:
470+
logger.debug("Setting expected token for REST endpoint"
471+
"on port {} to '{}'".format(rest_port, token))
472+
expected_token = token
473+
logger.debug("Starting REST thread")
474+
thread = threading.Thread(target=rest_function, name="REST thread",
475+
args=(logger, rest_port))
476+
thread.start()
421477

422478
# Start Tomcat last. It will be the foreground process.
423479
logger.info("Starting Tomcat")

0 commit comments

Comments
 (0)