Erlang application: different environment - erlang

What is the recommended way to have different values for application environment variables in an erlang application?
What I mean here is: how do you support different environment in your application (e.g. development, stage, production) in your erlang application? For example I would like tests using a specific fake service on a known host and production code use the real server on a different host.

You can use application config file as well. you can also pass the config as parameter while starting an erlang console that can help you in setting up environment variables. so you are pass test.config or production.config based on environment there by no need to compile the code and start them.
You can find more info here
http://www.erlang.org/doc/man/config.html

Dependency injection.
test_setup() -> [ {host,"http://..."}, ... ].
prod_setup() -> [ {host,"http://..."}, ... ].
test_start() -> start(test_setup()).
prod_start() -> start(prod_setup()).
start(Config) -> ... .
Alternately, policy modules. Make a policy whose interface matches the stuff you need, then pass in the name of the module containing the policy you want. Think ETS/DETS.

Related

How to use environment variables in CloudFlare Worker in local development environment

I have a CloudFlare Worker where I have environment variables set in the CF Settings..Environment Variables interface. I also have this wrangler.toml
In my worker's index.js I have code reading the variable REGISTRATION_API_URL. If the code is running in a deployed environment then it injects the value from the CF Settings into REGISTRATION_API_URL just fine.
But if I run
wrangler dev
or
wrangler dev --env local
then REGISTRATION_API_URL is undefined.
Originally I expected that the variable would be populated by the CF Settings values, but they aren't. So I tried the two vars setting in the wrangler.toml I show here but no difference. And I have spent a lot of time searching the docs and the greater web.
Are environment variables supported in a local dev environment? Any workarounds that people have come up with? Currently I am looking for undefined and defining the variable with a hard-coded value, but this is not a great answer.
Using wrangler 1.16.0
Thanks.
The docs could be more clear but if you are using the newer module syntax, the variables will not be available as global variables.
Environmental variables with module workers
When deploying a Module Worker, any bindings will not be available as global runtime variables. Instead, they are passed to the handler as a parameter – refer to the FetchEvent documentation for further comparisons and examples .
Here's an example.
export default {
async fetch(request, env, context) {
return new Response(env.MY_VAR);
},
};
KV namespaces are also available in the same object.
Maybe a bit late, but: no I don't think you can
But: you can always use self["YOUR_ENV_VARIABLE"] to get the value and then go from there (unfortunately the docs don't mention that)
Here is what I personally do in my Workers Site project to get the Release version (usually inserted via pipeline/action and then inserted via HtmlRewriter into the index.html):
const releaseVersion = self["RELEASE_VERSION"] || 'unknown'

Set Quarkus Logging Category Level via Environment Variables

In Spring, it is possible to set the Logging Category Level via environment variables. I've tried the same in a Quarkus application with the following logger declaration:
package org.my.group.resteasyjackson;
public class JacksonResource {
private static final Logger LOGGER = LoggerFactory.getLogger(JacksonResource.class);
#GET
public Set<Quark> list() {
LOGGER.info("Hello");
return quarks;
}
}
Executing the build artifact with
QUARKUS_LOG_CATEGORY_ORG_MY_LEVEL=WARN java -jar my-artifactId-my-version-runner.jar
will log anything at info level (since it is the default), therefore the "Hello" message.
However, inserting
quarkus.log.category."org.my".level=WARN
in the application.properties file works as desired. Are environment variables in this use case not usable for Quarkus applications?
Just tried with quarkus 1.13.1 and adding extra underscores for the quotes seems to work, try:
QUARKUS_LOG_CATEGORY__ORG_MY__LEVEL=WARN
You can do this:
quarkus.log.category."org.my".level=${LOG_LVL:INFO}
This simply means: use the log-level from my env variable "LOG_LVL" and if this is not present use INFO as default.
You can set this variable either as an env.variable or pass it through as system parameter during startup, but I'm not sure about the syntax as system parameter.
You should be able to use a system property (!= environment variable) like this:
java -Dquarkus.log.category.\"org.my\".level=WARN ...
Note: system properties will overrwite their application.properties, except for a quarkus.profile due to a bug.
No idea if environment variables can overwrite them too. Maybe the " need to be escaped. (I find environment variables brittle, I prefer system properties.)

define environment variable in traefik2 to be used in the file provider

How would one define environment variables for traefik2 so that they could be used within the dynamic file configuration ? e.g:
[http.routers]
[http.routers.the-rtr]
entrypoints = https
rule = Host(`rtr.$DOMAINNAME`)
where DOMAINNAME would have been defined somewhere (in a file, CLI arguments etc.)
Traefik's dynamic configuration does accept Go templating:
Traefik supports using Go templating to automatically generate repetitive portions of configuration files. These sections must be valid Go templates, augmented with the Sprig template functions.
See https://doc.traefik.io/traefik/providers/file/#go-templating
Note that Go Templating only works with dedicated dynamic configuration files. Templating does not work in the Traefik main static configuration file.
For example, if $DOMAINNAME is set as an environment variable, you can do
rule: Host(`{{ env "DOMAINNAME" | trimAll "\"" }}`)
Note: due to "env" quoting, the trimAll is needed — it might be better solution, but it's the better I've found so far.
Not sure if it's directly supported from traefik product.
I use file provider and in traefik.toml, I have:
[providers.file]
filename = "/etc/traefik/dynamic.config.toml"
watch = true
And I use separate mechanism like envsubst to generate (or regenerate as needed) the dynamic.config.toml file. Since I've watch = true, it gets loaded with latest info by traefik
Basically, the snipped you shared in the question can be used as a template file. Then use envsubst or similar to generate dynamic.config.toml.
Q&A on envsubst that I found useful: How to substitute shell variables in complex text files
Hope that helps.

Erlang how to pass parameter from module to another

I have an application written in erlang, i added a supervisor for distribution and now after parsing the configFile.cfg in the supervisor, i want to pass the configuration to my old application.
i have something like this now:
-module(supervisor_sup).
start() ->
application_app:start().
what i want is:
-module(supervisor_sup).
-record(config,{param1,param2}).
%After parsing the configFile.cfg
Conf = #config{param1 = Param1,
param2 = Param2},
start(Conf) ->
application_app:start(Conf).
It is uncommon to start applications from supervisors or modules under supervisors. The preferred way is to use application dependency to make sure all applications are started, and in the right order.
However, if you want some configuration to be available from several different applications without having to parse the configuration more than once, maybe the gproc library is what you are looking for?
https://github.com/uwiger/gproc
gproc can be used to efficiently set global configuration and much more. Even in a distributed environment.

Where should you put application properties in a rebar erlang application?

A newbie question: I wrote my first rebar based erlang application. I want to configure some basic properites like server host etc. Where is the best place to put them and how should I load them into the app?
The next steps are to make a release and create a node in it. A node runs your application in a standalone Erlang VM. A good starting point for creating a release using rebar:
Erlang Application Management with Rebar
Once you have created a release. The configuration properties for all applications in your node can then be added to
{your-app}/{release}/files/sys.config
You can read individual properties as follows:
Val = application:get_env(APP, KEY)
Alternatively, all properties for your application can be read as
Config = application:get_all_env(APP)
In sys.config, properties can be added as a proplist.
Example:
{myapp,
[
{port, 1234},
{pool_size, 5}
]
}

Resources