From 3405b121f5a16b138842d6659066c9822d536007 Mon Sep 17 00:00:00 2001
From: Erik Reid <erik.reid@geant.org>
Date: Wed, 6 May 2020 13:44:09 +0200
Subject: [PATCH] added boolean force param to /jobs/update

---
 inventory_provider/routes/jobs.py | 23 ++++++++----
 test/test_job_routes.py           | 59 +++++++++++++++++++++++++++++--
 2 files changed, 73 insertions(+), 9 deletions(-)

diff --git a/inventory_provider/routes/jobs.py b/inventory_provider/routes/jobs.py
index c9234fbc..de1edade 100644
--- a/inventory_provider/routes/jobs.py
+++ b/inventory_provider/routes/jobs.py
@@ -1,4 +1,5 @@
-from flask import Blueprint, current_app, jsonify, Response
+import distutils
+from flask import Blueprint, current_app, jsonify, Response, request
 from inventory_provider.tasks import worker
 from inventory_provider.routes import common
 from inventory_provider.tasks.common import get_current_redis, get_latch
@@ -15,13 +16,21 @@ def after_request(resp):
 @common.require_accepts_json
 def update():
 
+    force = request.args.get('force', default='false', type=str)
+    try:
+        force = distutils.util.strtobool(force)
+    except ValueError:
+        force = False
+
     config = current_app.config['INVENTORY_PROVIDER_CONFIG']
-    latch = get_latch(get_current_redis(config))
-    if latch and latch['pending']:
-        return Response(
-            response='an update is already in progress',
-            status=503,
-            mimetype="text/html")
+
+    if not force:
+        latch = get_latch(get_current_redis(config))
+        if latch and latch['pending']:
+            return Response(
+                response='an update is already in progress',
+                status=503,
+                mimetype="text/html")
 
     job_ids = worker.launch_refresh_cache_all(
         current_app.config["INVENTORY_PROVIDER_CONFIG"])
diff --git a/test/test_job_routes.py b/test/test_job_routes.py
index 81cc2fb1..a3508b37 100644
--- a/test/test_job_routes.py
+++ b/test/test_job_routes.py
@@ -30,9 +30,10 @@ TASK_STATUS_SCHEMA = {
 
 
 def test_job_update_all(client, mocker):
+    expected_task_ids = ['abc', 'def', 'xyz@123#456']
     launch_refresh_cache_all = mocker.patch(
         'inventory_provider.tasks.worker.launch_refresh_cache_all')
-    launch_refresh_cache_all.return_value = ['abc', 'def', 'xyz@123#456']
+    launch_refresh_cache_all.return_value = expected_task_ids
 
     rv = client.post(
         'jobs/update',
@@ -40,7 +41,61 @@ def test_job_update_all(client, mocker):
     assert rv.status_code == 200
     task_id_list = json.loads(rv.data.decode('utf-8'))
     jsonschema.validate(task_id_list, TASK_ID_LIST_SCHEMA)
-    assert len(task_id_list) == 3
+    assert set(task_id_list) == set(expected_task_ids)
+
+
+def test_job_update_force_pending(client, mocker):
+    expected_task_ids = ['22', 'agfafg', 'asf#asdf%111', '234']
+    launch_refresh_cache_all = mocker.patch(
+        'inventory_provider.tasks.worker.launch_refresh_cache_all')
+    launch_refresh_cache_all.return_value = expected_task_ids
+
+    mocked_get_latch = mocker.patch(
+        'inventory_provider.routes.jobs.get_latch')
+    mocked_get_latch.return_value = {'pending': True}
+
+    rv = client.post(
+        'jobs/update?force=true',
+        headers=DEFAULT_REQUEST_HEADERS)
+    assert rv.status_code == 200
+    task_id_list = json.loads(rv.data.decode('utf-8'))
+    jsonschema.validate(task_id_list, TASK_ID_LIST_SCHEMA)
+    assert set(task_id_list) == set(expected_task_ids)
+
+
+def test_job_update_pending_force_false(client, mocker):
+    def _assert_if_called(*args, **kwargs):
+        assert False
+    mocker.patch(
+        'inventory_provider.tasks.worker.launch_refresh_cache_all',
+        _assert_if_called)
+
+    mocked_get_latch = mocker.patch(
+        'inventory_provider.routes.jobs.get_latch')
+    mocked_get_latch.return_value = {'pending': True}
+
+    rv = client.post(
+        'jobs/update?force=no',
+        headers=DEFAULT_REQUEST_HEADERS)
+    assert rv.status_code == 503
+
+
+def test_job_update_pending(client, mocker):
+    def _assert_if_called(*args, **kwargs):
+        assert False
+    mocker.patch(
+        'inventory_provider.tasks.worker.launch_refresh_cache_all',
+        _assert_if_called)
+
+    mocked_get_latch = mocker.patch(
+        'inventory_provider.routes.jobs.get_latch')
+    mocked_get_latch.return_value = {'pending': True}
+
+    rv = client.post(
+        'jobs/update',
+        headers=DEFAULT_REQUEST_HEADERS)
+    assert rv.status_code == 503
+
 
 
 class MockedAsyncResult(object):
-- 
GitLab