-
Notifications
You must be signed in to change notification settings - Fork 16
feat(stable_config): add >100mb check for stable config files #1432
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
Open
vpellan
wants to merge
2
commits into
main
Choose a base branch
from
vpellan/stable-config-size-limit
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -543,14 +543,32 @@ impl Configurator { | |||||
| debug_messages.push(format!("\tlocal: {path_local:?}")); | ||||||
| debug_messages.push(format!("\tfleet: {path_managed:?}")); | ||||||
| } | ||||||
|
|
||||||
| let local_config = match fs::File::open(path_local) { | ||||||
| Ok(file) => match self.parse_stable_config_file(file) { | ||||||
| LoggedResult::Ok(config, logs) => { | ||||||
| debug_messages.extend(logs); | ||||||
| config | ||||||
| Ok(file) => { | ||||||
| match file.metadata() { | ||||||
| Ok(metadata) => { | ||||||
| // Fail if the file is > 100mb | ||||||
| if metadata.len() > 1024 * 1024 * 100 { | ||||||
| let anyhow_error = anyhow::anyhow!("Local file is too large (> 100mb)"); | ||||||
| let logged_result = LoggedResult::Err(anyhow_error); | ||||||
| return logged_result; | ||||||
| } | ||||||
| } | ||||||
| Err(e) => { | ||||||
| return LoggedResult::Err( | ||||||
| anyhow::Error::from(e).context("failed to get file metadata"), | ||||||
| ) | ||||||
| } | ||||||
| } | ||||||
| LoggedResult::Err(e) => return LoggedResult::Err(e), | ||||||
| }, | ||||||
| match self.parse_stable_config_file(file) { | ||||||
| LoggedResult::Ok(config, logs) => { | ||||||
| debug_messages.extend(logs); | ||||||
| config | ||||||
| } | ||||||
| LoggedResult::Err(e) => return LoggedResult::Err(e), | ||||||
| } | ||||||
| } | ||||||
| Err(e) if e.kind() == io::ErrorKind::NotFound => StableConfig::default(), | ||||||
| Err(e) => { | ||||||
| return LoggedResult::Err( | ||||||
|
|
@@ -559,13 +577,29 @@ impl Configurator { | |||||
| } | ||||||
| }; | ||||||
| let fleet_config = match fs::File::open(path_managed) { | ||||||
| Ok(file) => match self.parse_stable_config_file(file) { | ||||||
| LoggedResult::Ok(config, logs) => { | ||||||
| debug_messages.extend(logs); | ||||||
| config | ||||||
| Ok(file) => { | ||||||
| match file.metadata() { | ||||||
| Ok(metadata) => { | ||||||
| // Fail if the file is > 100mb | ||||||
| if metadata.len() > 1024 * 1024 * 100 { | ||||||
| let test = anyhow::anyhow!("Fleet file is too large (> 100mb)"); | ||||||
| return LoggedResult::Err(test); | ||||||
| } | ||||||
| } | ||||||
| Err(e) => { | ||||||
| return LoggedResult::Err( | ||||||
| anyhow::Error::from(e).context("failed to get file metadata"), | ||||||
| ) | ||||||
| } | ||||||
| } | ||||||
| LoggedResult::Err(e) => return LoggedResult::Err(e), | ||||||
| }, | ||||||
| match self.parse_stable_config_file(file) { | ||||||
| LoggedResult::Ok(config, logs) => { | ||||||
| debug_messages.extend(logs); | ||||||
| config | ||||||
| } | ||||||
| LoggedResult::Err(e) => return LoggedResult::Err(e), | ||||||
| } | ||||||
| } | ||||||
| Err(e) if e.kind() == io::ErrorKind::NotFound => StableConfig::default(), | ||||||
| Err(e) => { | ||||||
| return LoggedResult::Err( | ||||||
|
|
@@ -865,6 +899,64 @@ mod tests { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| #[test] | ||||||
| fn test_large_local_file() { | ||||||
| let configurator = Configurator::new(true); | ||||||
| let mut temp_local_file = tempfile::NamedTempFile::new().unwrap(); | ||||||
| let temp_fleet_file = tempfile::NamedTempFile::new().unwrap(); | ||||||
| let large_file = vec![b'a'; 1024 * 1024 * 100 + 1]; | ||||||
| temp_local_file.write_all(&large_file).unwrap(); | ||||||
| let temp_local_path = temp_local_file.into_temp_path(); | ||||||
| let temp_fleet_path = temp_fleet_file.into_temp_path(); | ||||||
| let result = configurator.get_config_from_file( | ||||||
| temp_local_path.to_str().unwrap().as_ref(), | ||||||
| temp_fleet_path.to_str().unwrap().as_ref(), | ||||||
| &ProcessInfo { | ||||||
| args: vec![b"-jar HelloWorld.jar".to_vec()], | ||||||
| envp: vec![b"ENV=VAR".to_vec()], | ||||||
| language: b"java".to_vec(), | ||||||
| }, | ||||||
| ); | ||||||
| match result { | ||||||
| LoggedResult::Ok(..) => panic!("Expected error"), | ||||||
| LoggedResult::Err(e) => { | ||||||
| assert_eq!( | ||||||
| e.to_string(), | ||||||
| "Local file is too large (> 100mb)".to_string() | ||||||
| ); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| #[test] | ||||||
| fn test_large_fleet_file() { | ||||||
| let configurator = Configurator::new(true); | ||||||
| let temp_local_file = tempfile::NamedTempFile::new().unwrap(); | ||||||
| let mut temp_fleet_file = tempfile::NamedTempFile::new().unwrap(); | ||||||
| let large_file = vec![b'a'; 1024 * 1024 * 100 + 1]; | ||||||
| temp_fleet_file.write_all(&large_file).unwrap(); | ||||||
| let temp_local_path = temp_local_file.into_temp_path(); | ||||||
| let temp_fleet_path = temp_fleet_file.into_temp_path(); | ||||||
| let result = configurator.get_config_from_file( | ||||||
| temp_local_path.to_str().unwrap().as_ref(), | ||||||
| temp_fleet_path.to_str().unwrap().as_ref(), | ||||||
| &ProcessInfo { | ||||||
| args: vec![b"-jar HelloWorld.jar".to_vec()], | ||||||
| envp: vec![b"ENV=VAR".to_vec()], | ||||||
| language: b"java".to_vec(), | ||||||
| }, | ||||||
| ); | ||||||
| match result { | ||||||
| LoggedResult::Ok(..) => panic!("Expected error"), | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| LoggedResult::Err(e) => { | ||||||
| assert_eq!( | ||||||
| e.to_string(), | ||||||
| "Fleet file is too large (> 100mb)".to_string() | ||||||
| ); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| #[test] | ||||||
| fn test_local_host_global_config() { | ||||||
| use LibraryConfigSource::*; | ||||||
|
|
||||||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 it by design that if one of them is too large, we bail out of stable config completely?
NIT: also was wondering if this check could be in a separate function which both local and fleet could reuse but not a big deal
Uh oh!
There was an error while loading. Please reload this page.
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.
@anna-git ,
If I remember correctly, we discussed this limitation a few months ago. For libraries that do not embed libdatadog for stable config -- like java and go -- we can attempt to open each file individually, and handle errors separately. It's my understanding that, in the libdatadog architecture, if either file is too big, we return a single error, and when the library consumes this error, it bails. Hence the behavior you described above. Correct?
And to my memory, we said there isn't a clean way to separate the error handling right now without breaking APIs, yes?
I really don't like this solution, since both inputs will have very different user experiences and thus should be logically separated, but I also acknowledge if it's the best we can do right now. In this case, can we add a comment in here that references a jira card that describes the issue behavior as well as how we might fix it in the future?
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 think it wouldn't be a problem to return a config without the keys from the faulty file, and just add the validation error to the messages of
LoggedResult. We could extendLoggedResultto contain error_messages and add the >100 mb error message in this vector. The tracers should read this vector always, and if they see it's filled up, log it as an error, so that it appears in error tracking as well. We just fill the error_messages, dont interrupt the function and just return an Ok() with whichever configs were read.If no file could be read at all(very rare...), I guess we could reallyl return an Error..