Add configuration validation in clients#59
Conversation
FlorianVeaux
left a comment
There was a problem hiding this comment.
I know it's still a draft, but I wanted to add a few comments already.
| instance.setLogIntakeConnectionBroken(true); | ||
| logger.severe("Connection broken, please double check both your Log Intake URL and Key"); | ||
| } | ||
| return; |
There was a problem hiding this comment.
So validation will pass even though both the url and the logIntakeUrl are invalid (or the apiKey is invalid).
Maybe we should at least fail it metrics can't be submitted?
Also to come back to the UI part, we should be able to display a FormWarning if the plugin can't connect.
There was a problem hiding this comment.
Oh that's a good idea. I agree there are more validations that can be performed.
| return this.jenkinsVersion; | ||
| } | ||
|
|
||
| private static boolean isCollectBuildLogEnabled(){ |
There was a problem hiding this comment.
I don't like that we need to access the config from here.
There was a problem hiding this comment.
This is also currently in DogstatsdClient. I'm not sure the best way to check for logs being enabled.
|
|
||
| return status; | ||
| }catch(Exception e){ | ||
| // Intercept all FormException instances. |
There was a problem hiding this comment.
I'm not sure what the effect of this is. Are we sure the change is safe ?
There was a problem hiding this comment.
Hm I'm not completely sure, I know FormExceptions are the most common, and they should be thrown, but maybe unexpected errors should be caught and logged.
There was a problem hiding this comment.
I added it back- I agree that having this safeguard is more important than the cleanliness of the code.
There was a problem hiding this comment.
In theory java should let you know about all exceptions and force you to catch or rethrow them except if they are unchecked exception like RuntimeExceptions.
So I think you should be able to ensure that all exceptions are caught?
|
|
||
| DatadogUtilities.severe(logger, e, null); | ||
| if(client != null) { | ||
| // There are no reasons at this point client should be null. |
There was a problem hiding this comment.
Let's update the comment here, client is expected to be null if connection is impossible.
There was a problem hiding this comment.
And let's reverse the condition:
if(client == null) {
return null
}
client.setDefaultIntakeConnectionBroken(false);
client.setLogIntakeConnectionBroken(false);
// Persist global configuration information
save();
return status;There was a problem hiding this comment.
I also think that instead of returning status here we should return true. And at the top of the method do this:
if(!super.configure(req, formData)){
return false
}|
|
||
| private static DatadogClient instance; | ||
| private static DatadogClient instance = null; | ||
| private static boolean failedLastValidation = false; |
There was a problem hiding this comment.
Let's have a comment to tell why it's useful.
| DatadogHttpClient newInstance = new DatadogHttpClient(url, logIntakeUrl, apiKey); | ||
| DatadogHttpClient httpInstance = (DatadogHttpClient) instance; | ||
| if (httpInstance != null && httpInstance.equals(newInstance)) { | ||
| if (DatadogHttpClient.failedLastValidation) { |
There was a problem hiding this comment.
We will need a way to retry validation every X minutes. What if failedLastValidation is true because of a network failure ? You'd require a restart of Jenkins to fix
There was a problem hiding this comment.
Hmm that's true. I will look into a way to do this.
There was a problem hiding this comment.
We still need this to be addressed
There was a problem hiding this comment.
I know, I haven't thought of a great approach yet. Do you have any ideas?
There was a problem hiding this comment.
So, thinking it through, in the case of a network failure, it wouldn't require a restart of jenkins, it would just require entering different credentials (and then entering the correct ones). It isn't the best solution, but I'm not sure how likely this scenario is.
| DatadogHttpClient.lastInstance = new DatadogHttpClient(url, logIntakeUrl, apiKey); | ||
| if (enableValidations) { | ||
| try { | ||
| validateCongiguration(url, logIntakeUrl, apiKey); |
There was a problem hiding this comment.
Reopening: this should not be a static method.
| DatadogHttpClient.instance = newInstance; | ||
| try { | ||
| validateCongiguration(url, logIntakeUrl, apiKey); | ||
| } catch(RuntimeException e){ |
There was a problem hiding this comment.
Let's not use unchecked exception for validation.
| this.logIntakeUrl = logIntakeUrl; | ||
| } | ||
|
|
||
| public static void validateCongiguration(String url, String logIntakeUrl, Secret apiKey) throws RuntimeException { |
There was a problem hiding this comment.
Typo: validateConfiguration*
There was a problem hiding this comment.
Let's use checked exception instead
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { |
There was a problem hiding this comment.
Auto generated ? Let's indicate it
There was a problem hiding this comment.
I based it off of the method from our other hashCode methods; it was recommended to override hashCode since I overrode equals
| import org.datadog.jenkins.plugins.datadog.util.TagsUtil; | ||
| import org.apache.commons.lang.StringUtils; | ||
|
|
||
| import java.io.*; |
There was a problem hiding this comment.
Same comments as for DatadogHttpClient
| if (enableValidations) { | ||
| DatadogHttpClient.instance = newInstance; | ||
| try { | ||
| newInstance.validateConfiguration(url, logIntakeUrl, apiKey); |
There was a problem hiding this comment.
| newInstance.validateConfiguration(url, logIntakeUrl, apiKey); | |
| newInstance.validateConfiguration(); |
You don't need the args because it's not static anymore
jetersen
left a comment
There was a problem hiding this comment.
I do not see how this PR fixes the issue of using the LogLevel.INFO
| <groupId>org.jenkins-ci.plugins</groupId> | ||
| <artifactId>plugin</artifactId> | ||
| <version>3.56</version> <!-- or whatever the newest version available is --> | ||
| <version>4.1</version> <!-- or whatever the newest version available is --> |
There was a problem hiding this comment.
This seems ill adviced:
https://github.com/jenkinsci/plugin-pom/blob/88cb710c1b7244bf5f885e16fc9f0baef1ef2661/pom.xml#L53
Please at least specify a Jenkins.version property
There was a problem hiding this comment.
Hi, @jetersen!
This change was to just update the parent pom version. It was also included in this PR as well, which is ready to be merged: https://github.com/jenkinsci/datadog-plugin/pull/57/files#diff-600376dffeb79835ede4a0b285078036R8 Adding a minimum jenkins version is out of the scope for this PR, but it’s a good idea that we should do in a later PR.
Thanks for the review @jetersen! I agree this PR doesn’t solve the issue of the continuous DatadogCountersPublisher logs- this was only meant to resolve the null api key logs issue. Can we use #63 to address the DatadogCountersPublisher issue? |
| return DatadogUtilities.getDatadogGlobalDescriptor() != null && | ||
| DatadogUtilities.getDatadogGlobalDescriptor().isCollectBuildLogs(); |
There was a problem hiding this comment.
Your doing a lookup twice 😓 and your using an more expensive get in the method called.
You should use:
ExtensionList.lookupSingleton(DatadogGlobalConfiguration.class);Also the method could be moved to the DatadogGlobalConfiguration class, basically moving it to where it belongs.
See here for example:
https://github.com/jenkinsci/azure-keyvault-plugin/blob/ef3a5eb4413f7ecd47d6532735604c52fceaaef0/src/main/java/org/jenkinsci/plugins/azurekeyvaultplugin/AzureKeyVaultGlobalConfiguration.java#L241-L243
There was a problem hiding this comment.
That sounds like a good idea, so we should refactor getDatadogGlobalDescriptor() and move it to DatadogGlobalConfiguration?
There was a problem hiding this comment.
There is definitely an opportunity to clean this up, but let's cover it in a separate PR.
There was a problem hiding this comment.
@sarah-witt I see you never picked up this suggestion 😅
There was a problem hiding this comment.
Ah you kept DatadogUtilities.getDatadogGlobalDescriptor 😅 Logically I would prefer DatadogGlobalConfiguration.get()
mgarabed
left a comment
There was a problem hiding this comment.
🔥 LGTM - tested this out locally and only see a single log line when the API key is invalid.
* Add configuration validation * Create .equals method and use synchronization * Remove try catch in configure and enforce use of POST * Simplify logic in configure * Don't create instance if config is invalid * Remove IOException * Throw form exception * Remove exception and post * Fiz style * Check for zero as port * Use parseInt instead of Number Utils * Remove zero check * Update pom * Fix style of imports * Add back extra safeguards for exceptions in configuration * Update exception type and use assertThrows in tests * Validation does not need parameters * Reset config for testing * Remove reset * Remove unneeded resetConfig * Remove unneeded validation * Move hostname validation * Style * Refactor validate url * Simplify equals methods * Update equals and remove imports * Update instance type
What does this PR do?
What inspired you to submit this pull request?
#55
Description of the Change
Alternate Designs
Possible Drawbacks
Verification Process
Additional Notes
Release Notes
Review checklist (to be filled by reviewers)
changelog/label attached. If applicable it should have thebackward-incompatiblelabel attached.do-not-merge/label attached.kind/andseverity/labels attached at least.