I’m using peer:start_link/1 to start a node, and I want to connect to it as a hidden node via shell. The net_kernel:hidden_connect_node/1 function does exactly what I want, but it’s undocumented. Why? Is there any other alternative?
There were some relevant discussions in the past:
Thanks, José!
It does not sound good to me. Is there a way to call peer:start_link/1
and pass the -hidden
option to it?
A fully connected mesh is not an option for me. I need a “master” node connected to “slave” nodes, but “slave” nodes should not be connected.
My current implementation is something like this:
start(Name, Host, Port, Apps) when
is_atom(Name), is_list(Host), is_integer(Port), is_list(Apps)
->
{ok, Ref, Node} = peer:start_link(#{
name => Name,
host => Host,
connection => Port
}),
ok = peer:call(Ref, code, add_paths, [code:get_path()]),
[
{ok, _} = peer:call(Ref, application, ensure_all_started, [App])
|| App <- Apps
],
true = peer:call(Ref, erlang, set_cookie, [erlang:get_cookie()]),
true = net_kernel:hidden_connect_node(Node),
Ref.
It works as intended, but can I achieve this another way without the net_kernel:hidden_connect_node/1
?
Any help is appreciated
Ok, so I ended up starting all nodes via the terminal.
My goal is to have a structure like this:
foo * * master * * baz
*
*
bar
And not a mesh, like:
foo * * master * * baz
* * *
* * *
* bar *
And this is something I have ended up with:
- Start the slave nodes:
$ erl -sname foo@localhost -setcookie foo -connect_all false
$ erl -sname bar@localhost -setcookie bar -connect_all false
- Start and setup the master node:
$ erl -sname master@localhost -setcookie master
(master@localhost)1> erlang:set_cookie(foo@localhost, foo).
true
(master@localhost)2> net_kernel:connect_node(foo@localhost).
true
(master@localhost)3> erlang:set_cookie(bar@localhost, bar).
true
(master@localhost)4> net_kernel:connect_node(bar@localhost).
true
(master@localhost)5> nodes().
[foo@localhost,bar@localhost]
- Result in slave nodes:
(foo@localhost)1> nodes().
[master@localhost]
(bar@localhost)1> nodes().
[master@localhost]
The reason for keeping the slave nodes unconnected is security. I’ve no idea if this can be really secure since cookies intent is not security.
I would appreciate any good article, book, suggestion, video, or anything related to this topic.
I’m a newbie in distribution. It’s a challenging subject for me. Thanks!
Edit
I’ve just realized I can achieve the same result by using peer
in the master node shell:
erl -sname master@localhost
Erlang/OTP 27 [erts-15.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Eshell V15.1 (press Ctrl+G to abort, type help(). for help)
(master@localhost)1> {ok, Foo, _} = peer:start_link(#{name => foo@localhost, args => ["-connect_all", "false"], connection => 0}).
{ok,<0.97.0>,foo@localhost}
(master@localhost)2> {ok, Bar, _} = peer:start_link(#{name => bar@localhost, args => ["-connect_all", "false"], connection => 0}).
{ok,<0.99.0>,bar@localhost}
(master@localhost)3> erlang:set_cookie(foo@localhost, foo).
true
(master@localhost)4> erlang:set_cookie(bar@localhost, bar).
true
(master@localhost)5> peer:call(Foo, erlang, set_cookie, [foo]).
true
(master@localhost)6> peer:call(Bar, erlang, set_cookie, [bar]).
true
(master@localhost)7> net_kernel:connect_node(foo@localhost).
true
(master@localhost)8> net_kernel:connect_node(bar@localhost).
true
(master@localhost)9> nodes().
[foo@localhost,bar@localhost]
(master@localhost)10> peer:call(Foo, erlang, nodes, []).
[master@localhost]
(master@localhost)11> peer:call(Bar, erlang, nodes, []).
[master@localhost]
It seems that the Erlang distribution is not what I need in that case. I can always access the master node and all information about other nodes via RPC, so I’m considering moving to a gen_tcp
interface. BTW, I’m still accepting suggestions
Relevant sources:
Some time ago I created a MeshxNode package. In short it is a custom carrier protocol implementation using service mesh for transport and discovery. It would be possible to leverage for example Consul intentions to control communication between nodes. I didn’t update this for a long time, possibly it will not even work with current Consul version.
Yes. In fact, you can start the peer node with any distribution option you like, or even with no distribution. You can also use it to test the distribution itself! Take a look at connection argument, specifically, standard_io
control channel option.
With that option, you can still use peer:call
to make RPC calls via control channel (not distribution).
It appears similar to structure created by this test case in the OTP codebase: otp/lib/kernel/test/pg_SUITE.erl at master · erlang/otp · GitHub
That’s exactly what standard_io
was designed for. If you look at peer documentation, there is a Docker example that goes even further - it starts peer nodes in a separate container! Potentially, it could be a remote host just as well.
Thanks a lot! The example in the pg_SUITE is exactly what I was looking for. I don’t need net_kernel:hidden_connect_node/1
anymore.