Set admin security context in the action execution checker thread
Change-Id: I4c7abff04b8797618294d9e13fbec4b5876bcdb6 Closes-Bug: #1805080
This commit is contained in:
parent
09ad2eebe4
commit
3153f1ca58
@ -16,6 +16,7 @@ import datetime
|
|||||||
import eventlet
|
import eventlet
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from mistral import context as auth_ctx
|
||||||
from mistral.db import utils as db_utils
|
from mistral.db import utils as db_utils
|
||||||
from mistral.db.v2 import api as db_api
|
from mistral.db.v2 import api as db_api
|
||||||
from mistral.engine import action_handler
|
from mistral.engine import action_handler
|
||||||
@ -71,6 +72,17 @@ def handle_expired_actions():
|
|||||||
def _loop():
|
def _loop():
|
||||||
global _stopped
|
global _stopped
|
||||||
|
|
||||||
|
# This is an administrative thread so we need to set an admin
|
||||||
|
# security context.
|
||||||
|
auth_ctx.set_ctx(
|
||||||
|
auth_ctx.MistralContext(
|
||||||
|
user=None,
|
||||||
|
tenant=None,
|
||||||
|
auth_token=None,
|
||||||
|
is_admin=True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
while not _stopped:
|
while not _stopped:
|
||||||
try:
|
try:
|
||||||
handle_expired_actions()
|
handle_expired_actions()
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import cachetools
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
@ -77,3 +78,51 @@ class ActionHeartbeatTest(base.EngineTestCase):
|
|||||||
name='std.noop',
|
name='std.noop',
|
||||||
state=states.ERROR
|
state=states.ERROR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Make sure actions are not sent to an executor.
|
||||||
|
@mock.patch.object(
|
||||||
|
rpc_clients.ExecutorClient,
|
||||||
|
'run_action',
|
||||||
|
mock.MagicMock()
|
||||||
|
)
|
||||||
|
@mock.patch.object(
|
||||||
|
cachetools.LRUCache,
|
||||||
|
'__getitem__',
|
||||||
|
mock.MagicMock(side_effect=KeyError)
|
||||||
|
)
|
||||||
|
def test_fail_action_with_missing_heartbeats_wf_spec_not_cached(self):
|
||||||
|
wf_text = """---
|
||||||
|
version: '2.0'
|
||||||
|
|
||||||
|
wf:
|
||||||
|
tasks:
|
||||||
|
task1:
|
||||||
|
action: std.noop
|
||||||
|
"""
|
||||||
|
|
||||||
|
wf_service.create_workflows(wf_text)
|
||||||
|
|
||||||
|
wf_ex = self.engine.start_workflow('wf')
|
||||||
|
|
||||||
|
# The workflow should fail because the action of "task1" should be
|
||||||
|
# failed automatically by the action execution heartbeat checker.
|
||||||
|
self.await_workflow_error(wf_ex.id)
|
||||||
|
|
||||||
|
with db_api.transaction():
|
||||||
|
wf_ex = db_api.get_workflow_execution(wf_ex.id)
|
||||||
|
|
||||||
|
t_execs = wf_ex.task_executions
|
||||||
|
|
||||||
|
t_ex = self._assert_single_item(
|
||||||
|
t_execs,
|
||||||
|
name='task1',
|
||||||
|
state=states.ERROR
|
||||||
|
)
|
||||||
|
|
||||||
|
a_execs = db_api.get_action_executions(task_execution_id=t_ex.id)
|
||||||
|
|
||||||
|
self._assert_single_item(
|
||||||
|
a_execs,
|
||||||
|
name='std.noop',
|
||||||
|
state=states.ERROR
|
||||||
|
)
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Action execution checker didn't set a security context before failing
|
||||||
|
expired action executions. It caused ApplicationContextNotFoundException
|
||||||
|
in case if corresponding workflow specification was not in the cache and
|
||||||
|
Mistral had to load a DB object. The DB operation in turn was trying
|
||||||
|
to access a security context which wasn't set. It's now fixed by setting
|
||||||
|
an admin context in the action execution checker thread.
|
Loading…
Reference in New Issue
Block a user