Open anuruddhal opened 3 years ago
The platform does not yet support this.
In the meantime, can we store the complete Config.toml
file in a ConfigMap resource and mount it as a volume on to the pod? In addition to this, you need to give the path of the Config.toml
via the BALCONFIGFILE
env variable.
You can have a environment variable whose value is TOML. At least in Linux, you can have 128k of environment variables.
@sameerajayasoma @jclark This feature was supported previously, however seems to be removed from a recent version on. IMO in the cloud native perspective, using env variables is the more intuitive than using toml, at least for the simple usecases. If cannot be done immediately, do we have a timeline to support this? Can we use the getEnv('xxx')
method from the os
package as a substitute for this functionality, if this will not be supported?
We should allow them to be specified on the command-line also: an option would specify a value for a single configurable variable, and could be repeated to specify multiple variables.
In the previous config API, configs were considered from multiple sources. So whether the configs were defined in a file or as env vars, they could be looked up through the config API. And there was a precedence defined to resolve conflicts which could arise with the same config key defined in multiple sources. The precedence (in order of increasing priority) was conf-file < env vars < CLI args
e.g., if there was a config key named foo.bar
in the config file, if needed the user could override it by providing a new value to it either through an env var or a CLI arg.
Use of the config API was then like a lookup on this collated source of configs.
Will it be possible to support the same or a similar behaviour with the configurable feature as well?
Refer to this specification that defines how values can be supplied to configurable variables via TOML syntax and command-line arguments.
However, we are not planning to support supplying individual values via environment variables. Use the following environment variables to supply the toml file or the contents of the toml file. Read this section in the spec for more details.
Reopening the issue as this topic came up in a discussion of implementation of micro service samples.
Communicating from one miroservice to another is a common use case. You can see an example here. Other languages usually uses env variables for this purpose. https://github.com/GoogleCloudPlatform/microservices-demo/blob/521602c7f6e097b095dba4b899714134b3005362/kubernetes-manifests/checkoutservice.yaml#L41
If we use confiugrables we have to keep everything in one env variable. https://github.com/xlight05/gcp-microservices-demo/blob/79976216b188b0b7336546ec54337db614ed9dd7/src/docker-compose.yml#L11 This can be complex when we have to replace the values in CICD pipelines and when we use tools kustomize to replace the value.
We already have two ways to supply values to configurable variables:
Config.toml
file.boolean | int | float | decimal | string | xml
Here is an approach to supply values via environment variables:
S
.
type S boolean | int | float | decimal | string | xml
configurable
variable of S with the structured identifier p.q.r.s
that conforms to [[org .] module .] variable
, can be configured via an environment variable of the form BAL_CONFIG_P_Q_R_S
.BAL_CONFIG_
prefix is used to identify environment variables defined for Ballerina programs. The toString()
representation of the value can be provided with an environment variable.
Type of value | Representation of the value | Parse |
boolean | toString()
|
boolean:fromString()
|
string | toString()
|
use as-is |
int | toString()
|
int:fromString()
|
float | toString()
|
float:fromString()
|
decimal | toString()
|
decimal:fromString()
|
xml | toString()
|
xml:fromString()
|
Examples: With command-line arguments:
bal run -- -Cballerina.log.level="DEBUG"
Environment variables:
BAL_CONFIG_BALLERINA_LOG_LEVEL="DEBUG" bal run
We already have two ways to supply values to configurable variables:
Config.toml
file.Command-line args
- Only for configurable variables of type
boolean | int | float | decimal | string | xml
Here is an approach to supply values via environment variables:
Allowed only for configurable variables of type
S
.
type S boolean | int | float | decimal | string | xml
- Each
configurable
variable of S with the structured identifierp.q.r.s
that conforms to[[org .] module .] variable
, can be configured via an environment variable of the formBAL_CONFIG_P_Q_R_S
.BAL_CONFIG_
prefix is used to identify environment variables defined for Ballerina programs.- Each part in the structured identifier is converted to uppercase, and dots are converted to underscores.
The
toString()
representation of the value can be provided with an environment variable.Type of value Representation of the value Parse boolean
toString()
boolean:fromString()
stringtoString()
use as-is inttoString()
int:fromString()
floattoString()
float:fromString()
decimaltoString()
decimal:fromString()
xmltoString()
xml:fromString()
Examples: With command-line arguments:bal run -- -Cballerina.log.level="DEBUG"
Environment variables:
BAL_CONFIG_BALLERINA_LOG_LEVEL="DEBUG" bal run
This should be perfect for code to cloud related use cases. The supported toml features will be same as Command-line args right?
Just to understand, whats stopping us from supporting records as well? Is it the toml table arrays?
@xlight05 AFAIK, we use string processing to support the command-line configuration. And configuring types like structures, and lists can make the logic more complex as we need to handle underlying types such as fields and elements. Plus the fromString()
of such values can contain special characters which need to be handled.
From the implementation perspective,
With the latest spec, the orgName
and moduleName
of a variable can be optional depending on its module. Is this apply to the env-variable case as well? Otherwise, it might not be consistent with the other configuration methods.
In addition to the ambiguity cases we handle for TOML & CLI syntax (both at compile-time and runtime), this will add another possible ambiguity depending on the case. As we support the alphanumeric characters in org & module names, users can have different modules with names Foo
and foo
in the same package.
Should we restrict having such configurable variables at compile-time or runtime?
One of the limitation of using environment variables is, configurable variables with quoted identifiers.
According to [1] "Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase letters, digits, and the '_' (underscore) from the characters defined in Portable Character Set and do not begin with a digit."
[1] https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html
@sameerajayasoma @jclark This feature was supported previously, however seems to be removed from a recent version on. IMO in the cloud native perspective, using env variables is the more intuitive than using toml, at least for the simple usecases. If cannot be done immediately, do we have a timeline to support this? Can we use the
getEnv('xxx')
method from theos
package as a substitute for this functionality, if this will not be supported?
This a legitimate requirement. Use case I'm implementing is:
https://cloud.google.com/run/docs/configuring/services/containers#configure-port
"For Cloud Run services, Cloud Run injects the PORT environment variable into the container. The container should listen on the port defined by the PORT environment variable rather than a specific hardcoded port. "
With help of @pcnfernando I can confirm that getEnv()
is a good start for a substitute.
` int PORT = check int:fromString(os:getEnv("PORT"));
service http:Service /foo on new http:Listener(PORT) { `
For a better solution, it would be good to have
os:getEnvOrDefault( <envvar>, <default-value-if-not-defined> )
function.
I'm +1 for going ahead with @sameerajayasoma proposal above. I don't see any major negative comments above .. if there is can someone restate it please? We can also introduce an annotation so users can override the (potentially ugly) default computed environment variable name.
As per the offline discussion with @warunalakshitha and @sameerajayasoma, the following design decisions were taken.
The environment variable-based configuration will have the highest precedence in the configuration methods. The provided values will be overridden accordingly. The order will be as follows,
BAL_CONFIG_FILES
- environment variable with file locationBAL_CONFIG_DATA
- environment variable with file contentConfig.toml
in the current working directory - By defaultThe environment variable name will have a prefix of BAL_CONFIG_VAR_
instead of BAL_CONFIG_
.
Because there are two kinds of environment variables used in Ballerina.
BAL_CONFIG_FILES
, BAL_CONFIG_DATA
.BAL_CONFIG_VAR_
will differentiate this and provide auto-mapping for configurable variables.
Description: We need to support reading configurable values from environment variables as many Cloud applications depend on configurations via env.
Please refer https://12factor.net/
Suggested Labels:
Code sample that shows issue:
Related Issues: https://github.com/ballerina-platform/ballerina-lang/issues/28327