irods: Calling `failmsg` and `fail` msi via the PREP fails with `RE_TYPE_ERROR`

Bug Report

iRODS Version, OS and Version

iRODS 4.2.11/4.3.0 centos7/almalinux8

What did you try to do?

I tried to call failmsg via callback in the Python Rule Engine Plugin.

Expected behavior

Not to see -1230000 RE_TYPE_ERROR , and expect the action that calls the failmsg fails.

Observed behavior (including steps to reproduce, if applicable)

I wanted to fire the PEP below by adding a metadata. I expect it to fail with errors “-169000 SYS_NOT_ALLOWED” in the client side. Also I wanted to see the ADMINISTRATIVE_METADATA message in the logs.

def pep_api_mod_avu_metadata_pre(rule_args, callback, rei):
    callback.failmsg(-169000, "ADMINISTRATIVE_METADATA")
    #callback.error("SYS_NOT_ALLOWED")
    #callback.msiOprDisallowed()

But I get -1230000 RE_TYPE_ERROR.

[irods@dev-u0137480 irods]$ imeta add -d test.txt atr val
remote addresses: 10.0.2.100 ERROR: Level 0: DEBUG: simplify: unsolvable typing constraint STRING * STRING < INTEGER * STRING.

line 0, col 7
failmsg(*ARG0,*ARG1)
       ^


remote addresses: 10.0.2.100 ERROR: rcModAVUMetadata failed with error -1230000 RE_TYPE_ERROR

logs:

irods stdout | May  5 16:02:52 pid:3208 DEBUG: simplify: unsolvable typing constraint STRING * STRING < INTEGER * STRING.
irods stdout | line 0, col 7
irods stdout | failmsg(*ARG0,*ARG1)
irods stdout |        ^
irods stdout | {"log_category":"legacy","log_facility":"local0","log_level":"error","log_message":"simplify: unsolvable typing constraint STRING * STRING < INTEGER * STRING.\n\nline 0, col 7\nfailmsg(*ARG0,*ARG1)\n       ^\n\n","request_api_name":"MOD_AVU_METADATA_AN","request_api_number":706,"request_api_version":"d","request_client_user":"rods","request_host":"10.0.2.100","request_proxy_user":"rods","request_release_version":"rods4.3.0","server_host":"dev-u0137480.irods.t.icts.kuleuven.be","server_pid":3208,"server_timestamp":"2023-05-05T14:02:52.882Z","server_type":"agent"}
irods stdout | {"log_category":"legacy","log_facility":"local0","log_level":"error","log_message":"caught python exception: Traceback (most recent call last):\n  File \"/etc/irods/core.py\", line 52, in pep_api_mod_avu_metadata_pre\n    callback.failmsg(-169000, \"ADMINISTRATIVE_METADATA\")\nRuntimeError: [iRods__Error__Code:-1230000] [-]\t/irods_source/server/re/include/irods/irods_re_plugin.hpp:333:irods::error irods::dynamic_operation_execution_manager<std::tuple<>, RuleExecInfo *, irods::DONT_AUDIT_RULE>::call(const std::string &, const std::string &, OP, As &&...) [T = std::tuple<>, C = RuleExecInfo *, Audit = irods::DONT_AUDIT_RULE, OP = std::function<irods::error (const std::string &, irods::re_pack_inp<std::tuple<>> &, irods::unpack &&)>, As = <const std::string &, irods::re_pack_inp<std::tuple<>> &, irods::unpack>] :  status [RE_TYPE_ERROR]  errno [] -- message [applyRuleUpdateParams failed for rule failmsg]\n\t[-]\t/irods_source/plugins/rule_engines/irods_rule_language/src/irods_rule_language.cpp:324:irods::error exec_rule(irods::default_re_ctx &, const std::string &, std::list<boost::any> &, irods::callback) :  status [RE_TYPE_ERROR]  errno [] -- message [applyRuleUpdateParams failed for rule failmsg]\n\n\n","request_api_name":"MOD_AVU_METADATA_AN","request_api_number":706,"request_api_version":"d","request_client_user":"rods","request_host":"10.0.2.100","request_proxy_user":"rods","request_release_version":"rods4.3.0","server_host":"dev-u0137480.irods.t.icts.kuleuven.be","server_pid":3208,"server_timestamp":"2023-05-05T14:02:52.885Z","server_type":"agent"}

Note: These msi(s) work well in the native rule engine. Also, other msi like writeLine or msiOprDisallowed have no issue in the PREP.

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Comments: 20 (11 by maintainers)

Most upvoted comments

@mstfdkmn - we’ll check into how to fail properly from a Python dynamic PEP.

@mstfdkmn - You need to return the (negative integer) error code from the *_pre PEP.

The original example contained something more of this style:

def pep_api_mod_avu_metadata_pre(rule_args,callback,rei):
    return error_code_with_message(irods_errors.SYS_NOT_ALLOWED, 
                                   "something bogus is afoot!", callback)

Notice the “return” there, which made sure an error code actually gets returned from the Python rule. If the pep_<OPERATION>_pre PEP does not contain an explicit return statement, to return the negative integer code of the indicated iRODS error to the rule framework, then effectively zero (aka a success code) will be returned, causing the <OPERATION> itself to go through as normal.

Hello @d-w-moore, I was able to build microservices and my test showed it worked as you described above. I am thinking to install them in our production environment however I wonder if I should expect these microservices will be officially released in 4.3.1. Thanks.

No official decision has been made on whether these MSIs will be included in a 4.3 release. When we know more, we’ll be sure to let the community know.

Sorry one last thing - where is the irods_errors -built in module- documented? I could find neither irods_rule_engine_plugin_python nor irods repository. I checked available irods error messages by print(dir(irods_errors)) though.

@d-w-moore ping

It’s likely that failmsg and other microservices are only meant to be used from the NREP.

However, there’s no reason we can’t implement microservices that support the following:

  • Callable from any REP
  • Adds an error code and message to the rError stack (for the client)
    • e.g. msi_rError_append(code:int, msg:string)
  • Logs a message at a specific log level
    • e.g. msi_log(log_category:string, log_level:string, msg:string)

Calling these microservices would not cause any rule to fail. The policy implementer would still need to follow the recommendations documented by the REP. But, they would at least have a flexible way to achieve the wanted behavior.