-
Notifications
You must be signed in to change notification settings - Fork 348
pacemaker-remoted load_env_var refactors, and assorted minor changes #3833
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
Conversation
883c023
to
8481902
Compare
3ebf24e
to
6a42764
Compare
Were you able to test the changes to load_env_vars? That, or some unit tests, would make me feel a whole lot better about all that small batch string processing code. |
Not really. That's gonna take me a little while to set up and figure out (won't be ready today during business hours). But it is a good idea. Also interested in whether there's a better way than rolling our own parser, but haven't found anything yet. |
I'm planning to use I think the authors made the |
Okay, I'll wait to do final review on this until after you've moved to using
I absolutely agree. If I were writing this function from scratch, I would (1) have it take file contents as a parameter instead of a file name, (2) put it in a library somewhere as private API to allow us to unit test it, and (3) find something in glib that could be used to do the parsing instead of writing it by hand. Now we're stuck with having to support whatever bugs there might be in processing since otherwise we'll break people's remote nodes. |
Not necessarily. Obviously we've run into many situations where users are relying on behavior they shouldn't be... but these corner cases seem like pretty clear bugs that shouldn't be guaranteed to work, and that it's unlikely anyone is using. I'd be willing to gamble, if we actually feel like fixing them. That's not something I want to spend time on right now though. If we find a good parser in a library, fine. But setting flags for quote nesting levels, whether we just saw a backslash and are escaping the next character, etc., sounds really unappealing. |
6a42764
to
cfbf4a4
Compare
Rebased on current main, which led to dropping the final commit. Otherwise no changes. |
cfbf4a4
to
c94342c
Compare
I added a commit to fix the I have not tested yet. |
ec1ad9f
to
f71ef81
Compare
81b5104
to
d561a8b
Compare
f1b55a0
to
7e60792
Compare
Still need to test the I can't easily test the But this actually resolves all the Coverity issues on my laptop. There is a suppression for |
cf12b21
to
f94c34d
Compare
@nrwahl2 Is there anything else remaining to be done on this PR? |
Only testing, hopefully. There is no unit testing yet, which may be overkill now that we rely on a handful of GLib function calls... but more importantly I haven't tested this by creating a bundle and making sure it loads environment variables appropriately. I need to refresh on how to do that. |
eebcadc
to
8f73fbb
Compare
Updated the "Standardize remote environment variable parsing" commit substantially, to resolve an issue where leading whitespace in an unquoted value was allowed. Also added a commit to a document a couple of limitations that I don't feel like dealing with. No changes to earlier commits. About to rebase on current main to resolve conflict. |
Note that delay_max != delay_base implies that delay_max > delay_base. Signed-off-by: Reid Wahl <[email protected]>
Add 1 to the modulus so that we include the full range of (delay_max - delay_base), not that it really matters. For example, if delay_max == 5 and delay_base == 2, then we want to add values in {0, 1, 2, 3} to delay_base -- not to add values only in {0, 1, 2}. Signed-off-by: Reid Wahl <[email protected]>
The current callers won't have trailing newlines from the CLI or from reading from a file. Newlines would be present only if the user included them explicitly. Newline removal was (re-)added by b7fe638, to fix a regression in 28ca6aa. However, at the time of 28ca6aa, pcmk_scan_nvpair() was public API, so the change in behavior actually mattered. Now, it doesn't. It appears to be safe to stop stripping trailing newlines. Signed-off-by: Reid Wahl <[email protected]>
I don't see any reason not to. This does change behavior for crm_resource and stonith_admin if "NAME=" is given as a command line argument. However, this is such an edge case that I don't expect it to matter. It seems foolish to depend on the current behavior. Of course, that means nothing, so if anyone complains, we can revert. Signed-off-by: Reid Wahl <[email protected]>
Better than defining our own swab functions if they're not available on the system. GLib already did that work for us and uses arch-specific optimizations where possible. Signed-off-by: Reid Wahl <[email protected]>
Coverity has been complaining about the payload_offset and payload_uncompressed being tainted scalar values. There's only so much validation we can do when we're reading from a socket. But apparently this is enough, because it makes the Coverity errors go away. There's a lot more room for improvement in the remote message processing. I found a few bugs a while back that we need to fix involving multiple messages received in rapid succession. This is an improvement for now. Note that I got rid of the CRM_LOG_ASSERT() line that subtracts 1 from the index. As far as I can tell, that's an off-by-one error and we have no reason to expect that position to contain a null byte. The commit that added it doesn't have any information in the commit message or comments. Signed-off-by: Reid Wahl <[email protected]>
Signed-off-by: Reid Wahl <[email protected]>
Logic doesn't change otherwise. We just have to copy the "eat the rest of the line" bit. Signed-off-by: Reid Wahl <[email protected]>
getline() allocates a buffer large enough to hold the entire input line, avoiding the need to worry about LINE_MAX (which glibc doesn't enforce anyway). The man page says: "getline() reads an entire line from stream, storing the address of the buffer containing the text into *lineptr. The buffer is null-terminated and includes the newline character, if one was found." So for each line that we read, either it contains a newline or we've reached EOF. This makes the line-eating and a bit of the error-checking unnecessary. Also define a constant for the file name instead of taking an argument. Signed-off-by: Reid Wahl <[email protected]>
Skipping (or now, stripping) leading whitespace is one fewer thing we have to do ourselves. g_strchug() is defined to operate on a (gchar *), but it modifies its argument in place without allocating/rellocating/freeing memory, so it's safe. Since find_env_var_name() only needs to return one pointer now, it doesn't need output arguments. Signed-off-by: Reid Wahl <[email protected]>
After recent refactors, this is no longer necessary. We can just continue to the next outer loop iteration in the one place where it would have mattered. Signed-off-by: Reid Wahl <[email protected]>
Signed-off-by: Reid Wahl <[email protected]>
We consider the value invalid if anything besides whitespace or a comment (beginning with '#') follows it on the line. Further, we ignore all trailing whitespace after a valid value. So it's fine to strip all trailing whitespace, including a newline if present, before processing. Clearly we must now look for '\0' where we previously looked for '\n'. Signed-off-by: Reid Wahl <[email protected]>
We don't want to do this until after parsing the value, because a '#' character inside a quoted value should be treated as part of the value. Signed-off-by: Reid Wahl <[email protected]>
By stripping the rest of the trailing whitespace after stripping the comment, we eliminate the need to null-terminate explictly. If the value is valid (not followed by any garbage), then end already points to a terminating null byte after stripping the comment and remaining whitespace. Signed-off-by: Reid Wahl <[email protected]>
It's no longer needed outside this block. Signed-off-by: Reid Wahl <[email protected]>
The changes in this commit involve using (gchar *) strings and some dynamic allocation to make load_env_vars() easier to reason about. Previously, we tried to be as efficient as possible by reading a line into a buffer, iterating over it with multiple pointers, dividing it into name and value by insertion of a null terminator, etc. This is premature optimization. This function is not called along a path of execution where performance is so critical as to require this. In my opinion, clarity is more important. * Use pcmk__scan_nvpair() to separate the line on the equal sign. * Simplify name validation since we now have name as a separate string (before the equal sign) and don't need to return first and last pointers. * Skip the leading quote by converting it to a space and calling g_strchug() to memmove() value up by one position. This ensures that value still points to the beginning of the buffer, which simplifies freeing it later. Signed-off-by: Reid Wahl <[email protected]>
Signed-off-by: Reid Wahl <[email protected]>
Our bespoke code has been fragile and hard to understand at a glance. There were certainly corner cases involving nested quotes that were not handled in the way the shell would handle them. Now we use g_shell_parse_argv() instead, to mimic how the shell would process the value in a "NAME=VALUE" assignment statement. Signed-off-by: Reid Wahl <[email protected]>
At least on my machine, this one is no longer needed after all the recent refactors. Signed-off-by: Reid Wahl <[email protected]>
We can resolve these limitations if there's ever a need. For now, it's not worth the trouble of implementing and testing these missing capabilities. Signed-off-by: Reid Wahl <[email protected]>
8f73fbb
to
bb71085
Compare
I tested successfully with the following environment file, making sure the values were as expected. It's not pretty, just a quick-and-dirty thing that hits all the important cases I could think of. The comment at the top is the variables that should get set.
|
I'm trying to fix the Coverity issues that are popping up for #3832 and these are also appearing on my machine. There are some more I haven't reached yet.