From b192e00e2f11094b8666a5a3784c3db37ae5a438 Mon Sep 17 00:00:00 2001 From: Derek D Date: Wed, 17 Apr 2024 07:36:25 +0000 Subject: [PATCH] [#7552] Add serialize functionality for ExecMyRuleInp --- scripts/irods/test/test_dynamic_peps.py | 56 +++++++++++++ server/re/src/irods_re_serialization.cpp | 100 ++++++++++++++++++++++- 2 files changed, 155 insertions(+), 1 deletion(-) diff --git a/scripts/irods/test/test_dynamic_peps.py b/scripts/irods/test/test_dynamic_peps.py index ff4210ae17..93b97d51d8 100644 --- a/scripts/irods/test/test_dynamic_peps.py +++ b/scripts/irods/test/test_dynamic_peps.py @@ -492,3 +492,59 @@ def test_if_Genquery2Input_is_exposed__issue_7570(self): self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_1', self.user.zone_name]) self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_2', '0']) self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_3', '0']) + + @unittest.skipIf(plugin_name != 'irods_rule_engine_plugin-irods_rule_language' or test.settings.RUN_IN_TOPOLOGY, "Requires NREP and single node zone.") + def test_if_ExecMyRuleInp_is_exposed__issue_7552(self): + with temporary_core_file() as core: + avu_prefix = 'test_if_ExecMyRuleInp_is_exposed__issue_7552' + + # Add a rule to core.re which when triggered will add AVUs to the user's + # session collection. + core.add_rule(dedent(''' + pep_api_exec_my_rule_pre(*INSTANCE, *COMM, *STRUCTINP, *OUT) {{ + *v = *STRUCTINP.inpParamArray_0_inOutStruct; + msiModAVUMetadata('-C', '{self.user.session_collection}', 'add', '{avu_prefix}_0', *v, ''); + + *v = *STRUCTINP.inpParamArray_0_label; + msiModAVUMetadata('-C', '{self.user.session_collection}', 'add', '{avu_prefix}_1', *v, ''); + + *v = *STRUCTINP.inpParamArray_0_type; + msiModAVUMetadata('-C', '{self.user.session_collection}', 'add', '{avu_prefix}_2', *v, ''); + + *v = *STRUCTINP.inpParamArray_len; + msiModAVUMetadata('-C', '{self.user.session_collection}', 'add', '{avu_prefix}_3', *v, ''); + + *v = *STRUCTINP.inpParamArray_oprType; + msiModAVUMetadata('-C', '{self.user.session_collection}', 'add', '{avu_prefix}_4', *v, ''); + + *v = *STRUCTINP.myRule; + msiModAVUMetadata('-C', '{self.user.session_collection}', 'add', '{avu_prefix}_5', *v, ''); + + *v = *STRUCTINP.outParamDesc; + msiModAVUMetadata('-C', '{self.user.session_collection}', 'add', '{avu_prefix}_6', *v, ''); + }} + '''.format(**locals()))) + + try: + # Should trigger PEP + self.user.assert_icommand(['irule', "*C=*A++*B", "*A=potato%*B=tomato", "*C="]) + + self.user.assert_icommand(['imeta', 'ls', '-C', self.user.session_collection], 'STDOUT', [ + f'attribute: {avu_prefix}_0\nvalue: potato\n', + f'attribute: {avu_prefix}_1\nvalue: *A\n', + f'attribute: {avu_prefix}_2\nvalue: STR_PI\n', + f'attribute: {avu_prefix}_3\nvalue: 2\n', + f'attribute: {avu_prefix}_4\nvalue: 0\n', + f'attribute: {avu_prefix}_5\nvalue: @external rule {{ *C=*A++*B }}\n', + f'attribute: {avu_prefix}_6\nvalue: *C=\n', + ]) + + finally: + # Remove the AVUs + self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_0', "potato"]) + self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_1', "*A"]) + self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_2', "STR_PI"]) + self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_3', "2"]) + self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_4', "0"]) + self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_5', "@external rule {{ *C=*A++*B }}"]) + self.user.run_icommand(['imeta', 'rm', '-C', self.user.session_collection, f'{avu_prefix}_6', "*C="]) diff --git a/server/re/src/irods_re_serialization.cpp b/server/re/src/irods_re_serialization.cpp index 89969a26b8..5fb12f5167 100644 --- a/server/re/src/irods_re_serialization.cpp +++ b/server/re/src/irods_re_serialization.cpp @@ -2,6 +2,7 @@ #include "irods/irods_logger.hpp" #include "irods/irods_plugin_context.hpp" +#include "irods/msParam.h" #include "irods/rodsErrorTable.h" #include @@ -1199,6 +1200,102 @@ namespace irods::re_serialization } } // serialize_vector_of_strings_ptr + static irods::error serialize_execMyRuleInp_ptr(boost::any _p, serialized_parameter_t& _out) + { + try { + log_re::trace(__func__); + const auto* casted_ptr = boost::any_cast(_p); + if (!casted_ptr) { + _out["execMyRuleInp_ptr"] = "nullptr"; + return SUCCESS(); + } + _out["myRule"] = casted_ptr->myRule; + _out["addr_hostAddr"] = casted_ptr->addr.hostAddr; + _out["addr_zoneName"] = casted_ptr->addr.zoneName; + _out["addr_portNum"] = boost::lexical_cast(casted_ptr->addr.portNum); + _out["addr_dummyInt"] = boost::lexical_cast(casted_ptr->addr.dummyInt); + serialize_keyValPair(casted_ptr->condInput, _out); + _out["outParamDesc"] = casted_ptr->outParamDesc; + + const auto* msparamarray_ptr = casted_ptr->inpParamArray; + if (!msparamarray_ptr) { + _out["inpParamArray"] = "nullptr"; + return SUCCESS(); + } + _out["inpParamArray_len"] = boost::lexical_cast(msparamarray_ptr->len); + _out["inpParamArray_oprType"] = boost::lexical_cast(msparamarray_ptr->oprType); + for (int i = 0; i < msparamarray_ptr->len; i++) { + std::string prefix = fmt::format("inpParamArray_{}_", i); + const auto* lbl = msparamarray_ptr->msParam[i]->label; + const auto* typ = msparamarray_ptr->msParam[i]->type; + _out[prefix + "label"] = lbl ? lbl : "nullptr"; + _out[prefix + "type"] = typ ? typ : "nullptr"; + const auto* msparam_ptr = msparamarray_ptr->msParam[i]; + + if (msparam_ptr == nullptr || msparam_ptr->inOutStruct == nullptr || !typ) { + _out[prefix + "inOutStruct"] = "nullptr"; + } + else if (strcmp(msparam_ptr->type, STR_MS_T) == 0) { + _out[prefix + "inOutStruct"] = static_cast(msparam_ptr->inOutStruct); + } + else if (strcmp(msparam_ptr->type, INT_MS_T) == 0) { + _out[prefix + "inOutStruct"] = std::to_string(parseMspForPosInt(const_cast(msparam_ptr))); + } + else if (strcmp(msparam_ptr->type, DOUBLE_MS_T) == 0) { + double out = 0.0; + if (parseMspForDouble(const_cast(msparam_ptr), &out)) { + THROW(SYS_INVALID_INPUT_PARAM, "Failed to convert microservice argument to float."); + } + _out[prefix + "inOutStruct"] = std::to_string(out); + } + else if (strcmp(msparam_ptr->type, FLOAT_MS_T) == 0) { + float out = 0.0; + if (parseMspForFloat(const_cast(msparam_ptr), &out)) { + THROW(SYS_INVALID_INPUT_PARAM, "Failed to convert microservice argument to float."); + } + _out[prefix + "inOutStruct"] = std::to_string(out); + } + else { + _out[prefix + "inOutStruct"] = fmt::format("unrepresentable_type_{}", msparam_ptr->type); + } + const auto* ptr = msparamarray_ptr->msParam[i]->inpOutBuf; + if (ptr) { + _out[prefix + "inpOutBuf_len"] = boost::lexical_cast(ptr->len); + std::string& str = _out[prefix + "inpOutBuf_buf"]; + + for (int j = 0; j < ptr->len; j++) { + unsigned char c = *(static_cast(ptr->buf) + j); + + if (isprint(c) || isspace(c) || isblank(c)) { + str += c; + } + else { + str += fmt::format("\\x{0:02x}", c); + } + } + } + else { + _out[prefix + "null_value"] = "null_value"; + } + } + return SUCCESS(); + } + catch (const boost::bad_any_cast& e) { + return ERROR(INVALID_ANY_CAST, + fmt::format("{}: failed to cast pointer to [execMyRuleInp_t*]: {}", __func__, e.what())); + } + catch (const irods::exception& e) { + return ERROR( + e.code(), + fmt::format( + "{}: failed to cast pointer to [execMyRuleInp_t*]: {}, ec: {}", __func__, e.what(), e.code())); + } + catch (const std::exception& e) { + return ERROR( + SYS_LIBRARY_ERROR, fmt::format("{}: failed to serialize [execMyRuleInp_t*]: {}", __func__, e.what())); + } + } // serialize_execMyRuleInp_ptr + #if 0 static error serialize_XXXX_ptr( boost::any _p, @@ -1255,7 +1352,8 @@ namespace irods::re_serialization {std::type_index(typeid(bytesBuf_t*)), serialize_bytesBuf_ptr}, {std::type_index(typeid(Genquery2Input*)), serialize_Genquery2Input_ptr}, {std::type_index(typeid(const std::vector*)), serialize_const_vector_of_strings_ptr}, - {std::type_index(typeid(std::vector*)), serialize_vector_of_strings_ptr}}; + {std::type_index(typeid(std::vector*)), serialize_vector_of_strings_ptr}, + {std::type_index(typeid(execMyRuleInp_t*)), serialize_execMyRuleInp_ptr}}; return the_map; } // get_serialization_map