-
Notifications
You must be signed in to change notification settings - Fork 189
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
Review the generation of the datadog.conf to make it more flexible and maintainable #222
Conversation
Hi @aerostitch, Although I'm rooting for generic solutions, we decided to keep the entrypoint as "dumb" as possible to avoid tricky side-effects. But I agree it leads to restrictions on what it can do (for example we refuse mapping list/dict types to avoid parsing errors). For more advanced usages, our recommendation for kubernetes is storing datadog.yaml in a configmap, could that work for you? |
Hey @xvello ,
Short answer: no
Problems it would generate:
This solution would work as a **temporary** solution though I'd rather have
a builtin solution because I would need to track down every changes made in
the default config file for each upgrade.
I don't want to loose a day on an upgrade just because one default
parameter has been added to the default config file that I overwrite.
Proposed alternatives:
- If you want I can make it raise exceptions on bad json format if you're afraid of having it too smart! XD
- Worse case I can add an environment variable juste for the percentiles config. But that really looks like overcomplicating the maintenance. (I'm already not sure why you went through the pain of having 2 shell & bash scripts that end up doing the same stuff when you distribute a python environment. - yes I know alpine doesn't have bash built in but if you want to evolve supporting more distros it would seem more logical to have something that works for all like a python script with symlinks in each folder specific for a repo for example)
Side note: There's already a ton of logic in the shell scripts. I don't think you can really still qualify it as "dumb" 😉
Other side note: I'd be totally be down to put the full logic of the environment variables management into a python script (that could even use configParser so that we avoid any problems) to lower the amount of shell that need to be manage here. Just tell me if you're interested.
Joseph
|
Hi Joseph, I agree with you, we do need to work on something more maintainable than 5 different entrypoints that get out of sync on a regular basis. I actually created a backlog card for that yesterday between merging #220 & #223 and reading your PR ;) Indeed, I do think it would be great to use ConfigParser to load the default config, add envvar bindings (including a generic json one) and write the updated configuration. We would lose comments, but I think that's an acceptable tradeoff. That would also solve our current limitation of not being able to map array/mapping types in the yaml files. A generic json payload that would be parsed and injected in the configuration would indeed solve that. I'd like to get @hkaj's input on that before going forward though, he'll be back in the office on Tuesday. In the meantime, do you want me to add that binding, old-style? |
Please go forward if you have time. My main concern is how this would transfer to agent6 later. We designed agent6 with envvar binding out of the box for the main configuration, but that does not cover the integrations' configuration. As we'll continue shipping python 2.7 in agent6, I guess we would still use that script for them. |
Hey @xvello , Sorry for the late answer, last days have been very busy. Thanks |
Hi @aerostitch, Please go forward on this PR, to keep the full context. |
3fcc1eb
to
86e3fe0
Compare
So I have a slightly different proposition than passing the json around:
Note: using the ConfigParser makes you loose the comments and also changes the separator from Other node: for now I've only done the datadog.conf management as an example. Not sure what's the status of agent6 and if we could integrate this idea of generic |
a44e297
to
8538d25
Compare
Note: the symlink doesn't work but we can use the same idea of calling |
4eea2ac
to
e37973b
Compare
@hkaj , @xvello I think I finished the refactoring. Let me know if that looks good to you. Adding the capability to use Thanks |
e37973b
to
28c9e87
Compare
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.
Hi @aerostitch
Thanks for the PR! I had a look at it and left a few comments.
Binding settings to env var is a good idea, but we need to be careful about what we bind and what takes precedence between defaults, env vars and files.
For datadog.conf it's okay because most settings have sane defaults, and the scope is small. But for integrations I don't think we should allow individual overrides as that can (and will) get hairy.
I suggest using your approach for datadog.conf, and keeping the old entrypoint approach for integrations and supervisor (we don't do much with supervisor, I don't think it's worth changing it).
The other interesting point you raised is the duplication of the entrypoints. As @xvello discovered earlier, docker hub now builds on docker cloud, so we can specify the dockerfile name for builds. Allowing us to move all entrypoints at the root of docker-dd-agent and thus sharing a single entrypoint between them. That would solve this issue, and also make these good old sed
s way simpler to read than a Python script that does the same thing (for integrations and supervisor. Again I think the Python script is necessary for datadog.conf).
What do you think?
config_builder.py
Outdated
# This will store the config parser object that is used in the different functions | ||
self.config = None | ||
|
||
def set_instance_property(self, integration, property_key, property_value): |
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 a pretty hacky way to configure checks, I don't think we should support this interface. There is a plan to allow passing a check config file as json through an environment, but it will be for the whole config file, we don't plan on supporting individual setting overrides.
We could add this check config through env var thing now if that's a blocker for you but mounting them in /conf.d
should do the trick in most cases.
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.
Not sure what's hacky in that. It just opens the integration config file (from the example or from the existing one if any) and updates the property for the instance (or the several instances if several ones are already defined).
It looks more complex but in the long term it would be more maintainable than having to change 6 sed in 6 entrypoint.sh no?
That function is generic and is only used in 'build_integration_conf` which is just a rewrite in python of their shell counterpart present in several of the entrypoints. Looks more maintainable on the long term no?
And when we switch to allow environment variables (which we do for some in build_integration_conf
) we wouldn't really have to modify it.
Note: the generic DD_<integration_name>_<property_name>
idea have not been implemented this PR.
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.
Not sure what's hacky in that
Fair enough, I wasn't clear here. It certainly is more flexible, but this is bound to fail in unexpected ways as config files change, and we observed that this kind of config-level failures tend to confuse users a lot, leading to frustration, and unnecessary support tickets.
It will also greatly limit our freedom in revamping config files in fear that someone is editing them with an ad-hoc system like this one.
It looks more complex but in the long term it would be more maintainable than having to change 6 sed in 6 entrypoint.sh
Again, we don't expect this to grow much (but rather to shrink with agent 6) and we'll reduce the number of entrypoint files. Integration config should be modified by passing whole files, not individual settings. Those we have in the entrypoint now are special cases that we want to get rid of progressively, not generalize.
config_builder.py
Outdated
with open(_target, 'w') as _stream: | ||
yaml.dump(_data, _stream, default_flow_style=False) | ||
|
||
def build_integration_conf(self): |
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 a rewrite of the check settings we change in the entrypoint in Python. What I like about it is that it's all in one place, what I don't like is that it's more complex than the entrypoint sed
s.
What we could do to make the entrypoint situation better is to modify the structure of docker-dd-agent to share the entrypoint between all images. If we do that, does keeping the sed-ing in the entrypoint sound reasonable to you?
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.
It looks more clear and flexible to me to do that. And I was thinking about adding the ability to have properties via a hash, not only 1 property at a time. Would that be clearer?
Keeping the sed in the entrypoints will depend on if we want to have a good maintainability or not. All entrypoints do different stuffs. Some start dogstatsd, some start supervisord, it means maintaining several entrypoints, so the less code is in the entrypoint scripts, the more maintainable it will be.
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.
I was thinking about adding the ability to have properties via a hash, not only 1 property at a time
dict or individual, this is not an interface we want to support. Integration configs should be all or nothing. Those we touch in entrypoints are special cases that we'll work on getting rid of, not extending.
All entrypoints do different stuffs
That's true, we can't magically merge them together without adding any complexity at all. That's why I'm okay with the datadog.conf part.
config_builder.py
Outdated
with open(config_file, 'wb') as cfd: | ||
self.config.write(cfd) | ||
|
||
def build_supervisor_conf(self): |
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.
same here, this is less clear than the 3 seds and 1 echo we have now for supervisor config. I see the added complexity but not the added value.
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.
3 sed in 6 dockerfile and 6 entrypoint.sh (for now)....
Why doing things 3 different ways? If we do a python script for maintaining part of the config, why not reuse the function for the rest?
Right now supervisor.conf has 3 parameters changed, meaning 3 sed.
How maintainable will it be when you want to change the 10 others?
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.
We probably won't, and supervisor will most definitely go away with agent 6 anyway. That's also why adding complexity around it is a no go.
config_builder.py
Outdated
|
||
self.save_config(self.supervisor_conf_file) | ||
|
||
def build_datadog_conf(self): |
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.
For datadog.conf I agree it's a good idea to allow individual overrides, and binding all settings to env var is a good way to do that (that's actually what agent 6 will do).
Thanks for the review @hkaj . The different entrypoints start different things so having Dockerfile in just one location (which would be great) won't solve all the maintainability issues. I think keeping things in different shell scripts is what made things difficult to maintain in the 1st place. Not sure it's the best route to go. Would better documentation or better comments help? |
28c9e87
to
1f1eb0c
Compare
thanks for the details @aerostitch |
Ok, so as a summary:
I'll check that today. |
That's a great summary, we'll handle the dockerfile move as it requires changing docker hub settings. We can also take care of the entrypoints if you prefer focusing on datadog.conf. Thanks again! |
The datadog.conf is pretty much done. |
8dc4075
to
2c3a26c
Compare
Note: I did remove the examples from the |
b8c90df
to
5513d29
Compare
Hey @hkaj, I did the changes we discussed earlier. I removed the examples from the Also there's Let me know what you think of this version. Thanks |
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.
Nice, I left a few comments and we'll need to test it carefully for regressions but it looks really good!
Dockerfile-dogstatsd
Outdated
&& sed -i -e"s/^.*non_local_traffic:.*$/non_local_traffic: yes/" /etc/dd-agent/datadog.conf \ | ||
&& sed -i -e"s/^.*log_to_syslog:.*$/log_to_syslog: no/" /etc/dd-agent/datadog.conf \ | ||
&& mv /supervisor.conf /etc/dd-agent/supervisor.conf | ||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ |
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.
\
is not needed
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.
Good catch. fixed.
Dockerfile-dogstatsd-alpine
Outdated
AGENT_VERSION=5.16.0 \ | ||
DD_ETC_ROOT="/opt/datadog-agent/agent" \ | ||
PATH="/opt/datadog-agent/venv/bin:/opt/datadog-agent/agent/bin:$PATH" \ | ||
PATH="${DD_HOME}/venv/bin:${DD_HOME}/bin:${PATH}" \ |
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.
these 2 path lines can be simplified into PATH="${DD_HOME}/agent/bin:${DD_HOME}/venv/bin:${DD_HOME}/bin:$PATH"
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.
Actually, as we set them in the same ENV command, I had issues where variables were not set in the described order ending up in PATH=/venv/bin:/bin:${PATH}"
after evaluation so I've sticked to the full path and removed the other that I forgot to remove there.
Thx
entrypoint-dogstatsd.sh
Outdated
else | ||
# disable the agent when the env var is absent | ||
export DD_APM_ENABLED=false | ||
fi |
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.
should this block be in config_builder?
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.
I didn't find a clean way to set the environment variables from python to the outside shell.
But transformed it to be way simpler here: export DD_APM_ENABLED=${DD_APM_ENABLED:-false}
# To do this, we execute some of dd-agent's python code and expose the hostname | ||
# as an env var | ||
export DD_HOSTNAME=`python -c "from utils.hostname import get_hostname; print get_hostname()"` | ||
fi |
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.
ditto
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.
I didn't find a clean way to set the environment variables from python to the outside shell. Do you have one?
497f953
to
201958c
Compare
Rebased from master too. |
Sorry @hkaj I just realized that I didn't say that I updated the PR with your feedback last week. 😶 |
thanks @aerostitch |
That's a great improvement over There's a few more cleanup we could do (remove My only fear is about the While we investigate how to build chained images reliably, I'd go with reverting |
201958c
to
6790da3
Compare
Thans for the review @hkaj and @xvello . Thx |
Thanks @aerostitch |
thx! :) |
What does this PR do?
Provides the ability to add config parameters that are not controlled by environment variables yet
Motivation
I wanted a way to add those without overwriting the entire datadog.conf file.
Additional Notes
The python file has been added to the alpine folder to make it available for both the alpine distro and the classic one.
Edit
The initial content of this PR has evolved. Please read the conversation for more details.
Closes: #213