How to use/set Application parameters with `rebar3 shell`?

I’m using Erlang for a PA which, among other things, includes a TCP server. To facilitate testing the system with several Erlang nodes running all on the same computer I’d like to have this TCP server listening on the same port but on different IPs (127.0.0.1, 127.0.0.2, &c).

I searched a bit and Application parameters (app(4) env config, application:get_env/3) seem to be what I need: application:get_env(my_application, ipaddr, {127, 0, 0, 1}). In the my_application.app.src file I can specify these variables already, it works!

However, for the original goal of running the same application several times on the same computer, I was looking for a way to specify/override these defaults with the rebar3 shell command. I searched online but still haven’t found a good way to do this.

More specifically, I tried using rebar3 shell --config but haven’t figured out how because it doesn’t work for me. I’ve tried using -my_application ipaddr '{127, 0, 0, 2}' as suggested in the erl docs but rebar3 complains that it’s an invalid option (fair enough).

I’ve also tried using the ERL_FLAGS OS environment variable (suggested here), which seems to be working(!) but isn’t very ergonomic (have to deal to shell expansion &c…).

Is there no other way? Being able to use a config file for each node would be ideal, so that I could more easily edit and use more complex Erlang terms as values. rebar3 shell --config looks exactly like what I want, but I can’t understand how I’m supposed to use it…

1 Like

You can set the config in the rebar.config. See how here.
Is this what you are looking for?

1 Like

You mean something like this?

% ...
{shell, [
    {config, "path/to/cfg.config"},
    {apps, [my_application]}
]}.

I had found this config parameter, but the problem is how to change it on each rebar3 shell invocation, to start different nodes with different configs.

2 Likes

Yes, I was referring to this.
For now, I have no idea, sorry.
I believe someone will help you,

1 Like

No problem, thanks anyway :slight_smile:

2 Likes

rebar3 shell --config path/to/sys.config

For automated testing i would recommend the new peer module.

1 Like

Thanks for the reply, I didn’t know about the peer module, will investigate it.

RE the --config option, can you provide an “template” sys.config? Is it similar to rebar.config in content? Asking because I’ve already tried using this option but failed.

1 Like

I believe this can help you:

2 Likes

One more recommendation on top of that, if you’re using Common Test, then ?CT_PEER macros are more robust compared to raw peer.

5 Likes

Awesome, thanks for the links, I think this will be it! I’ll test this later and reply again.

2 Likes

Yes, but only when running releases and it is allowed by relx’s sys_config_src option which allows you to specify template configuration file. It uses a simple templating system allowing you to embed your env variables into resulting sys.config. However, there is no option to do it when running rebar3 shell. Can someone provide more info on why this is missing and whether there is interest to add --config_src option to rebar3 shell command?

1 Like

Didn’t get the chance yesterday but just tried this and it worked, thanks for the links!

I wrote a few .config files like this:

[{my_application,[
  {addr, {127,0,0,1}},
  {servers, [<<"127.0.1.1">>,<<"127.0.1.2">>]}
]}].

And then ran the several nodes in different terminals with:

ERL_FLAGS='-config cfg1.config' rebar3 shell
ERL_FLAGS='-config cfg2.config' rebar3 shell
# etc
4 Likes

Good to know. In this case I don’t need template values, I just need a few different constants.

1 Like

There is no option because it is done (the replacement) in the generated relx start script. I think there is interest in supporting it.

3 Likes

Why not call app via IP_ADDR=1.2.3.4 rebar3 run and get it in-app via os:getenv(”IP_ADDR”)?

1 Like

Because environment variables are not as ergonomic to use as application parameters. Depending on the option, you may need to do extra processing (such as parsing a number or an IP address). With the proposed solution I went with you get Erlang terms out of the config variables.

1 Like