-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Read config values from env on init command #663
Conversation
* cluster and restapi configs can also get values from environment variables * other config components don't read any values from the environment License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have I missed anything?
What do you think?
I think that I'm stupid for not having realized you can set pointer fields on that struct to be able to distinguish between set and unset fields. And I have this SetIfNotDefault()
(https://github.com/ipfs/ipfs-cluster/blob/master/config/util.go#L56) thing which is the workaround to that and which would become an if src != nil ...
thing. Also probably simplifies the parseDuration
things.
That, or there was really some issue that I have totally forgotten.
That's just because we started adding envvar support to a couple of components as we needed. every component should get it though. |
I just noticed that |
Yes, please, implement for all. |
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
in LoadJSON for restapi and cluster Config License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
parseDuration := func(txt string, def time.Duration) time.Duration {
d, _ := time.ParseDuration(txt)
if d == 0 {
logger.Warningf("%s is not a valid duration. Default will be used", txt)
return def
}
return d
}
if jcfg.StateSyncInterval != nil {
cfg.StateSyncInterval = parseDuration(*jcfg.StateSyncInterval, cfg.StateSyncInterval)
} Any thoughts? |
Just noticed that |
Why is |
Also noticed that |
Probably because it was introduced later and not backported to all the places where it could be used. |
I think it's a bug, it should be bool in jsonConfig and it should not be ignored in ToJSON() (the idea is that it remains "hidden" when generating the json config"). |
Yes, because these fields are kept around for compatibility and the json config is parsed with the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I think things got uglier using pointers. I may have chosen not to use them because fields can still be set to empty values and then should be interpreted as "use the default value" in many cases.
Can we get this PR through without moving everything to pointers or is it a must?
If so, we should edit SetIfNotDefault
to handle nil pointer values and try to introduce as little if jsoncfg.Value != nil
as possible.
We can leave out the pointer fields. |
My intention with introducing pointer fields was to reuse the code in cfg := Config{}
// some values are now loaded from the given json
cfg.LoadJSON(rawJSON)
// the fields in `jsonConfig` that don't get any values from env will have zero values
// and will replace the fields that were set in the `rawJSON` used earlier
cfg.ApplyEnvVars() I might be wrong, but this is how I understood it worked. Using pointers made it easier to precisely figure out which fields had been set in both json and env with the same code. As far as I can tell, we either need to adapt the existing code to take into account that any config field can be empty, or write new code that would only parse env variables. Is this not the case? |
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
A little detail: type jsonMetricsConfig struct {
EnableStats bool `json:"enable_stats"`
PrometheusEndpoint string `json:"prometheus_endpoint"`
StatsReportingInterval string `json:"reporting_interval"`
} Is it ok if we rename In
type jsonTracingConfig struct {
EnableTracing bool `json:"enable_tracing"`
JaegerAgentEndpoint string `json:"jaeger_agent_endpoint"`
TracingSamplingProb float64 `json:"sampling_prob"`
TracingServiceName string `json:"service_name"`
} |
Another option would be to use the type jsonMetricsConfig struct {
EnableStats bool `json:"enable_stats"`
PrometheusEndpoint string `json:"prometheus_endpoint"`
StatsReportingInterval string `json:"reporting_interval" envconfig:"reportinginterval"`
} This requires less code changes. |
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
Hello, yes please, rename these in a different PR so they match the JSON key and so we can merge them asap for the upcoming release that introduces tracing. Thanks! cc ^^ @lanzafame |
Right. Can we do the Config.ToJSONConfig() -> apply envconfig -> Config.FromJSONConfig() thing in ApplyEnvVars() ? At least for the moment, to simplify this changeset. We can do the make-things-pointers as a follow up, but it uglifies things a bit and I have the feeling we'll introduce some bugs or behaviour change that is not obvious at the moment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what it would look like if we don't use pointer fields. I think these are the minimum needed changes.
Keep in mind that booleans like restapi.cors_allow_credentials can never be set to false unless that is the default value. It is impossible to figure out if restapi jsonConfig.CORSAllowCredentials is false because it wasn't set or CLUSTER_RESTAPI_CORSALLOWCREDENTIALS was set to false by the user.
Can we do the Config.ToJSONConfig() -> apply envconfig -> Config.FromJSONConfig() thing in ApplyEnvVars()
Do you still want to do this?
Yes, see comment below. Doing that should workaround the problem above and be reasonably safe for the moment.
Regarding smaller PRs, I got a bit carried away and wanted to fix everything in just one, but would you rather have the |
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
Get jsonConfig from Config, apply env vars to it, load jsonConfig back into Config. License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
Those are fine here. Thanks! |
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
Instead of adding an |
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
License: MIT Signed-off-by: Robert Ignat <robert.ignat91@gmail.com>
@roignpar is this good on your side? Looks ok to me! |
@hsanjuan Yep, I think it's done! |
Thanks so much! |
Thanks for all the feedback and patience! |
@hsanjuan this is what I had in mind for #656.
In short, I split
LoadJSON
into another method,applyConfigJSON
which only applies theconfigJSON
values to the originalConfig
and added theApplyEnvVars
method toConfig
which reads all env vars into aconfigJSON
and overrides them back intoConfig
.All the other
ComponentConfig
s have emptyApplyEnvVars
because they shouldn't read config from the env. At least that is what the docs say: https://cluster.ipfs.io/documentation/configuration/#using-environment-variables-to-overwrite-configuration-valuesI now notice that
LoadJSON
assumed values to be set in theconfigJSON
and thus will override config values with zero values if env vars are not set. Maybe we could have another method that allows all fields to be optional? Would it make sense to use only pointers for theconfigJSON
fields to be able to distinguish fields that were set more easily (they would benil
)? i.e.:Have I missed anything?
What do you think?