Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions doc/appendices/command-line/traffic_ctl_jsonrpc.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,42 @@ but rather to the rpc endpoint, so you can directly send requests and receive re
}
}


.. option:: invoke

Invoke a remote call by using the method name as parameter. This could be a handy option if you are developing a new handler or you
just don't want to expose the method in :program:`traffic_ctl`, for instance when implementing a custom handler inside a proprietary plugin.

.. option:: --params, -p

Parameters to be passed in the request, YAML or JSON format are accepted. If JSON is passed as param it should not
be mixed with YAML. It's important that you follow the :ref:`jsonrpc-protocol` specs. If the passed param does not
follows the specs the server will reject the request.

.. _rpc_invoke_example_1:

Example 1:

Call a jsonrpc method with no parameter.

.. code-block::

$ traffic_ctl rpc invoke some_jsonrpc_handler
--> {"id": "0dbab88d-b78f-4ebf-8aa3-f100031711a5", "jsonrpc": "2.0", "method": "some_jsonrpc_handler"}
<-- { response }

.. _rpc_invoke_example_2:

Example 2:

Call a jsonrpc method with parameters.

.. code-block::

$ traffic_ctl rpc invoke reload_files_from_folder --params 'filenames: ["file1", "file2"]' 'folder: "/path/to/folder"'
--> {"id": "9ac68652-5133-4d5f-8260-421baca4c67f", "jsonrpc": "2.0", "method": "reload_files_from_folder", "params": {"filenames": ["file1", "file2"], "folder": "/path/to/folder"}}
<-- { response }

Examples
========

Expand Down
1 change: 0 additions & 1 deletion doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ Please find the `jsonrpc 2.0 request` schema for reference ( `mgmt2/rpc/schema/j
* Optional parameters:



* ``params``:

A Structured value that holds the parameter values to be used during the invocation of the method. This member
Expand Down
4 changes: 2 additions & 2 deletions include/shared/rpc/RPCRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct JSONRPCRequest {
virtual std::string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dang, shouldn't that be std::string const&?

get_method() const
{
return "method";
return this->method;
}
};

Expand Down Expand Up @@ -225,4 +225,4 @@ operator<<(std::ostream &os, const JSONRPCError &err)

return os;
}
} // namespace shared::rpc
} // namespace shared::rpc
25 changes: 25 additions & 0 deletions src/traffic_ctl_jsonrpc/CtrlCommands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,12 @@ DirectRPCCommand::DirectRPCCommand(ts::Arguments args) : CtrlCommand(args)
_invoked_func = [&]() { from_file_request(); };
} else if (_arguments.get("input")) {
_invoked_func = [&]() { read_from_input(); };
} else if (_arguments.get("invoke")) {
_invoked_func = [&]() { invoke_method(); };
if (printOpts._format == BasePrinter::Options::Format::LEGACY) {
// overwrite this and let it drop json instead.
printOpts._format = BasePrinter::Options::Format::DATA_ALL;
}
}

_printer = std::make_unique<GenericPrinter>(printOpts);
Expand Down Expand Up @@ -458,6 +464,25 @@ DirectRPCCommand::read_from_input()
}
}

void
DirectRPCCommand::invoke_method()
{
shared::rpc::ClientRequest request;
if (auto method = _arguments.get("invoke"); method) {
request.method = method.value();
// We build up the parameter content if passed.
if (auto params = _arguments.get("params"); params) {
std::ostringstream ss;
for (auto &&param : _arguments.get("params")) {
ss << param;
ss << '\n';
}
request.params = YAML::Load(ss.str()); // let if fail if this is bad.
}
_printer->write_output(invoke_rpc(request));
}
}

//------------------------------------------------------------------------------------------------------------------------------------
ServerCommand::ServerCommand(ts::Arguments args) : CtrlCommand(args)
{
Expand Down
1 change: 1 addition & 0 deletions src/traffic_ctl_jsonrpc/CtrlCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ class DirectRPCCommand : public CtrlCommand
void from_file_request();
void get_rpc_api();
void read_from_input();
void invoke_method();
/// run a YAML validation on the input.
bool validate_input(std::string const &in) const;
};
Expand Down
11 changes: 0 additions & 11 deletions src/traffic_ctl_jsonrpc/jsonrpc/CtrlRPCRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,17 +221,6 @@ struct ShowRegisterHandlersRequest : shared::rpc::ClientRequest {
}
};
//------------------------------------------------------------------------------------------------------------------------------------
// We expect the method to be passed, this request is used to create dynamic requests by using (traffic_ctl rpc invoke "func_name")
struct CustomizableRequest : shared::rpc::ClientRequest {
using super = shared::rpc::ClientRequest;
CustomizableRequest(std::string const &methodName) { super::method = methodName; }
std::string
get_method() const
{
return super::method;
}
};
//------------------------------------------------------------------------------------------------------------------------------------
///
/// @brief Config status request mapping class.
///
Expand Down
6 changes: 5 additions & 1 deletion src/traffic_ctl_jsonrpc/traffic_ctl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,11 @@ main(int argc, const char **argv)
"No json/yaml parse validation will take place, the raw content will be directly send to the server.", "", 0, "",
"raw")
.add_example_usage("traffic_ctl rpc input ");

direct_rpc_command
.add_command("invoke", "Call a method by using the method name as input parameter", "", MORE_THAN_ONE_ARG_N,
[&]() { command->execute(); })
.add_option("--params", "-p", "Parameters to be passed in the request, YAML or JSON format", "", MORE_THAN_ONE_ARG_N, "", "")
.add_example_usage("traffic_ctl rpc invoke foo_bar -p \"numbers: [1, 2, 3]\"");
try {
auto args = parser.parse(argv);
argparser_runroot_handler(args.get("run-root").value(), argv[0]);
Expand Down